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/new docstrings styling #169

Merged
merged 9 commits into from
Sep 17, 2024
7 changes: 5 additions & 2 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,8 @@ jobs:
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache

- name: Run tests
run: make pipeline-test
- name: Run Sage doctests
run: make docker-test

- name: Run pytest
run: make docker-pytest
110 changes: 99 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,67 @@ docker-doc: docker-build
@make mount-volume-and-run && make generate-documentation && make stop-container-and-remove container_name="container-for-docs"

docker-test: docker-build
@docker run --name container-for-test -d -it ${image_name} sh && docker exec container-for-test sage -t --long -T 3600 --force-lib cryptographic_estimators && docker stop container-for-test && docker rm container-for-test
@echo "Removing previous container...."
@make stop-container-and-remove container_name="container-for-test" \
|| true
@echo "Creating container..."
@docker run --name container-for-test -d -it ${image_name} sh \
&& docker exec container-for-test sh -c " \
sage -t --long --timeout 3600 --force-lib \
# cryptographic_estimators/SDEstimator/ \
cryptographic_estimators/DummyEstimator/ \
cryptographic_estimators/LEEstimator/ \
cryptographic_estimators/MAYOEstimator/ \
cryptographic_estimators/MQEstimator/ \
cryptographic_estimators/MREstimator/ \
cryptographic_estimators/PEEstimator/ \
cryptographic_estimators/PKEstimator/ \
cryptographic_estimators/RegSDEstimator/ \
cryptographic_estimators/SDFqEstimator/ \
cryptographic_estimators/UOVEstimator/ \
cryptographic_estimators/base_algorithm.py \
cryptographic_estimators/base_constants.py \
cryptographic_estimators/base_estimator.py \
cryptographic_estimators/base_problem.py \
cryptographic_estimators/estimation_renderer.py \
cryptographic_estimators/helper.py \
" \
&& echo "All tests passed." \
|| echo "Some test have failed, please see previous lines."
@echo "Cleaning container..."
@make stop-container-and-remove container_name="container-for-test"


docker-testfast: docker-build
@docker run --name container-for-test -d -it ${image_name} sh && docker exec container-for-test sage -t cryptographic_estimators && make stop-container-and-remove container_name="container-for-test"
@echo "Removing previous container...."
@make stop-container-and-remove container_name="container-for-test" \
|| true
@echo "Creating container..."
@docker run --name container-for-test -d -it ${image_name} sh \
&& docker exec container-for-test sh -c " \
sage -t --timeout 3600 --force-lib \
# cryptographic_estimators/SDEstimator/ \
cryptographic_estimators/DummyEstimator/ \
cryptographic_estimators/LEEstimator/ \
cryptographic_estimators/MAYOEstimator/ \
cryptographic_estimators/MQEstimator/ \
cryptographic_estimators/MREstimator/ \
cryptographic_estimators/PEEstimator/ \
cryptographic_estimators/PKEstimator/ \
cryptographic_estimators/RegSDEstimator/ \
cryptographic_estimators/SDFqEstimator/ \
cryptographic_estimators/UOVEstimator/ \
cryptographic_estimators/base_algorithm.py \
cryptographic_estimators/base_constants.py \
cryptographic_estimators/base_estimator.py \
cryptographic_estimators/base_problem.py \
cryptographic_estimators/estimation_renderer.py \
cryptographic_estimators/helper.py \
" \
&& echo "All tests passed." \
|| echo "Some test have failed, please see previous lines."
@echo "Cleaning container..."
@make stop-container-and-remove container_name="container-for-test"

add-copyright:
@python3 scripts/create_copyright.py
Expand All @@ -88,17 +145,48 @@ docker-pytest:
|| true
@echo "Creating container..."
@docker run --name pytest-estimators -d -it ${image_name} sh \
&& docker exec pytest-estimators sh -c "sage --python3 -m pytest -n auto -vv \
--cov-report xml:coverage.xml --cov=${PACKAGE} \
&& ${SAGE} tests/SDFqEstimator/test_sdfq.sage \
&& ${SAGE} tests/LEEstimator/test_le_beullens.sage \
&& ${SAGE} tests/LEEstimator/test_le_bbps.sage \
&& ${SAGE} tests/PEEstimator/test_pe.sage \
&& ${SAGE} tests/PKEstimator/test_pk.sage" \
&& echo "All tests passed." \
|| echo "Some test have failed, please see previous lines."
&& docker exec pytest-estimators sh -c " \
pytest --doctest-modules -n auto -vv \
cryptographic_estimators/SDEstimator/ \
# cryptographic_estimators/DummyEstimator/ \
# cryptographic_estimators/LEEstimator/ \
# cryptographic_estimators/MAYOEstimator/ \
# cryptographic_estimators/MQEstimator/ \
# cryptographic_estimators/MREstimator/ \
# cryptographic_estimators/PEEstimator/ \
# cryptographic_estimators/PKEstimator/ \
# cryptographic_estimators/RegSDEstimator/ \
# cryptographic_estimators/SDFqEstimator/ \
# cryptographic_estimators/UOVEstimator/ \
# cryptographic_estimators/base_algorithm.py \
# cryptographic_estimators/base_constants.py \
# cryptographic_estimators/base_estimator.py \
# cryptographic_estimators/base_problem.py \
# cryptographic_estimators/estimation_renderer.py \
# cryptographic_estimators/helper.py \
# tests/ \
" \
@echo "Cleaning container..."
@make stop-container-and-remove container_name="pytest-estimators"


# docker-pytest:
# @echo "Removing previous container...."
# @make stop-container-and-remove container_name="pytest-estimators" \
# || true
# @echo "Creating container..."
# @docker run --name pytest-estimators -d -it ${image_name} sh \
# && docker exec pytest-estimators sh -c "sage --python3 -m pytest -n auto -vv \
# --cov-report xml:coverage.xml --cov=${PACKAGE} \
# && ${SAGE} tests/SDFqEstimator/test_sdfq.sage \
# && ${SAGE} tests/LEEstimator/test_le_beullens.sage \
# && ${SAGE} tests/LEEstimator/test_le_bbps.sage \
# && ${SAGE} tests/PEEstimator/test_pe.sage \
# && ${SAGE} tests/PKEstimator/test_pk.sage" \
# && echo "All tests passed." \
# || echo "Some test have failed, please see previous lines."
# @echo "Cleaning container..."
# @make stop-container-and-remove container_name="pytest-estimators"

docker-pytest-cov:
pytest -v --cov-report xml:coverage.xml --cov=${PACKAGE} tests/
17 changes: 17 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest


def pytest_addoption(parser):
parser.addoption(
"--skip-long-doctests",
action="store_true",
default=False,
help="Flag to skip long time execution doctests",
)


@pytest.fixture(autouse=True)
def add_longtests(request, doctest_namespace):
doctest_namespace["skip_long_doctests"] = request.config.getoption(
"--skip-long-doctests"
)
129 changes: 60 additions & 69 deletions cryptographic_estimators/SDEstimator/sd_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,26 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# ****************************************************************************

# ****************************************************************************
# Copyright 2023 Technology Innovation Institute

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# ****************************************************************************


import pytest
from math import inf
from ..SDEstimator.sd_algorithm import SDAlgorithm
from ..SDEstimator.sd_problem import SDProblem
from ..SDEstimator.SDAlgorithms import BJMMd2, BJMMd3, MayOzerovD2, MayOzerovD3
from ..base_estimator import BaseEstimator
from math import inf


class SDEstimator(BaseEstimator):
"""
Construct an instance of Syndrome Decoding Estimator

INPUT:

- ``n`` -- code length
- ``k`` -- code dimension
- ``w`` -- error weight
- ``excluded_algorithms`` -- a list/tuple of excluded algorithms (default: None)
- ``nsolutions`` -- no. of solutions
"""Construct an instance of Syndrome Decoding Estimator.

TODO: Maybe we should add the optional_parameters dictionary here?
Args:
n (int): Code length.
k (int): Code dimension.
w (int): Error weight.
excluded_algorithms (Union[List, Tuple], optional): A list or tuple of excluded algorithms. Defaults to None.
nsolutions (int): Number of solutions.

Todo:
* Maybe we should add the optional_parameters dictionary here?
"""

excluded_algorithms_by_default = [BJMMd2, BJMMd3, MayOzerovD2, MayOzerovD3]
Expand All @@ -64,27 +45,33 @@ def __init__(self, n: int, k: int, w: int, memory_bound=inf, **kwargs):

kwargs["excluded_algorithms"] += self.excluded_algorithms_by_default

super(SDEstimator, self).__init__(SDAlgorithm, SDProblem(
n, k, w, memory_bound=memory_bound, **kwargs), **kwargs)

def table(self, show_quantum_complexity=0, show_tilde_o_time=0,
show_all_parameters=0, precision=1, truncate=0):
"""
Print table describing the complexity of each algorithm and its optimal parameters

INPUT:

- ``show_quantum_complexity`` -- show quantum time complexity (default: true)
- ``show_tilde_o_time`` -- show Ō time complexity (default: true)
- ``show_all_parameters`` -- show all optimization parameters (default: true)
- ``precision`` -- number of decimal digits output (default: 1)
- ``truncate`` -- truncate rather than round the output (default: false)

EXAMPLES:

sage: from cryptographic_estimators.SDEstimator import SDEstimator
sage: A = SDEstimator(n=100, k=50, w=10)
sage: A.table()
super(SDEstimator, self).__init__(
SDAlgorithm,
SDProblem(n, k, w, memory_bound=memory_bound, **kwargs),
**kwargs
)

def table(
self,
show_quantum_complexity=0,
show_tilde_o_time=0,
show_all_parameters=0,
precision=1,
truncate=0,
):
"""Print table describing the complexity of each algorithm and its optimal parameters.

Args:
show_quantum_complexity (int, optional): Show quantum time complexity. Defaults to 0.
show_tilde_o_time (int, optional): Show Ō time complexity. Defaults to 0.
show_all_parameters (int, optional): Show all optimization parameters. Defaults to 0.
precision (int, optional): Number of decimal digits output. Defaults to 1.
truncate (int, optional): Truncate rather than round the output. Defaults to 0.

Examples:
>>> from cryptographic_estimators.SDEstimator import SDEstimator
>>> A = SDEstimator(n=100, k=50, w=10)
>>> A.table()
+---------------+---------------+
| | estimate |
+---------------+------+--------+
Expand All @@ -102,12 +89,14 @@ def table(self, show_quantum_complexity=0, show_tilde_o_time=0,
| Stern | 22.3 | 16.0 |
+---------------+------+--------+

TESTS:

sage: from cryptographic_estimators.SDEstimator import SDEstimator
sage: from cryptographic_estimators.SDEstimator import BothMay
sage: A = SDEstimator(n=100, k=42, w=13, bit_complexities=1,excluded_algorithms=[BothMay], workfactor_accuracy=25)
sage: A.table(show_tilde_o_time=1, precision=0) # long time
Tests:
>>> if skip_long_doctests:
... pytest.skip()
>>> from cryptographic_estimators.SDEstimator import SDEstimator
>>> from cryptographic_estimators.SDEstimator import BothMay
>>> A = SDEstimator(n=100, k=42, w=13, bit_complexities=1,excluded_algorithms=[BothMay], workfactor_accuracy=25)
>>> A.table(show_tilde_o_time=1, precision=0)
+---------------+---------------+------------------+
| | estimate | tilde_o_estimate |
+---------------+------+--------+-------+----------+
Expand All @@ -124,10 +113,10 @@ def table(self, show_quantum_complexity=0, show_tilde_o_time=0,
| Stern | 23 | 16 | 11 | 3 |
+---------------+------+--------+-------+----------+

sage: from cryptographic_estimators.SDEstimator import SDEstimator
sage: from cryptographic_estimators.SDEstimator.SDAlgorithms import BJMMdw
sage: A = SDEstimator(3488,2720,64,excluded_algorithms=[BJMMdw])
sage: A.table(precision=3, show_all_parameters=1) # long time
>>> from cryptographic_estimators.SDEstimator import SDEstimator
>>> from cryptographic_estimators.SDEstimator.SDAlgorithms import BJMMdw
>>> A = SDEstimator(3488, 2720, 64, excluded_algorithms=[BJMMdw])
>>> A.table(precision=3, show_all_parameters=1)
+---------------+--------------------------------------------------------------------------------+
| | estimate |
+---------------+---------+---------+------------------------------------------------------------+
Expand All @@ -144,10 +133,10 @@ def table(self, show_quantum_complexity=0, show_tilde_o_time=0,
| Stern | 151.409 | 49.814 | {'r': 7, 'p': 4, 'l': 39} |
+---------------+---------+---------+------------------------------------------------------------+

sage: from cryptographic_estimators.SDEstimator import SDEstimator
sage: from cryptographic_estimators.SDEstimator.SDAlgorithms import BJMMdw
sage: A = SDEstimator(3488,2720,64,excluded_algorithms=[BJMMdw],memory_access=3)
sage: A.table(precision=3, show_all_parameters=1) # long time
>>> from cryptographic_estimators.SDEstimator import SDEstimator
>>> from cryptographic_estimators.SDEstimator.SDAlgorithms import BJMMdw
>>> A = SDEstimator(3488,2720,64,excluded_algorithms=[BJMMdw],memory_access=3)
>>> A.table(precision=3, show_all_parameters=1)
+---------------+----------------------------------------------------------------------------+
| | estimate |
+---------------+---------+--------+---------------------------------------------------------+
Expand All @@ -163,9 +152,11 @@ def table(self, show_quantum_complexity=0, show_tilde_o_time=0,
| Prange | 173.447 | 21.576 | {'r': 7} |
| Stern | 153.015 | 32.587 | {'r': 7, 'p': 2, 'l': 21} |
+---------------+---------+--------+---------------------------------------------------------+

"""
super(SDEstimator, self).table(show_quantum_complexity=show_quantum_complexity,
show_tilde_o_time=show_tilde_o_time,
show_all_parameters=show_all_parameters,
precision=precision, truncate=truncate)
super(SDEstimator, self).table(
show_quantum_complexity=show_quantum_complexity,
show_tilde_o_time=show_tilde_o_time,
show_all_parameters=show_all_parameters,
precision=precision,
truncate=truncate,
)
Loading