From ae39e82fe4a29fa4ef23a0154802cece7cb0ffaf Mon Sep 17 00:00:00 2001 From: PatrickOHara Date: Fri, 7 Jul 2023 16:50:25 +0100 Subject: [PATCH 01/10] Formatting --- tests/test_walk.py | 1 + tspwplib/walk.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_walk.py b/tests/test_walk.py index 6304ff1..bc3731c 100644 --- a/tests/test_walk.py +++ b/tests/test_walk.py @@ -63,6 +63,7 @@ def test_order_edge_list(): with pytest.raises(NotSimpleException): order_edge_list(edges6) + def test_reorder_edge_list_from_root(): """Test edges are reordered starting and ending at root""" root = 0 diff --git a/tspwplib/walk.py b/tspwplib/walk.py index dd4a9c7..74b6d9b 100644 --- a/tspwplib/walk.py +++ b/tspwplib/walk.py @@ -4,7 +4,11 @@ from typing import Dict, Iterable, Mapping, Set import networkx as nx -from .exception import EdgesNotAdjacentException, NotSimpleException, NotSimpleCycleException +from .exception import ( + EdgesNotAdjacentException, + NotSimpleException, + NotSimpleCycleException, +) from .types import ( EdgeFunction, EdgeFunctionName, From e456d689a02d1b7f56c3c564a397df1432b413c7 Mon Sep 17 00:00:00 2001 From: Patrick O'Hara Date: Thu, 8 Sep 2022 16:50:51 +0100 Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=93=9D=20Fix=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements.txt | 2 +- tspwplib/problem.py | 2 +- tspwplib/walk.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 93deaf5..6628435 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black>=22.6.0 markdown-include>=0.6.0 mkdocs>=1.1.2 -mkdocstrings>=0.13.6 +mkdocstrings[python]>=0.19.0 mkdocs-material>=6.0.2 mypy>=0.971 pylint>=2.14.5 diff --git a/tspwplib/problem.py b/tspwplib/problem.py index 3925291..301d8f4 100644 --- a/tspwplib/problem.py +++ b/tspwplib/problem.py @@ -528,7 +528,7 @@ def __set_node_attributes(self, graph: nx.Graph, names: VertexLookup) -> None: graph.nodes[names[vertex]]["x"] = coord[0] graph.nodes[names[vertex]]["y"] = coord[1] - def get_weight(self, start, end) -> int: + def get_weight(self, start: int, end: int) -> int: """Return the weight of the edge between start and end. This method provides a single way to obtain edge weights regardless of diff --git a/tspwplib/walk.py b/tspwplib/walk.py index 74b6d9b..4d5015a 100644 --- a/tspwplib/walk.py +++ b/tspwplib/walk.py @@ -297,7 +297,7 @@ def total_prize_of_tour(prizes: Mapping[Vertex, int], tour: VertexList) -> int: Args: prizes: A mapping from vertices to prizes, e.g. dict, property map - vertices: List of vertices in the prizes map + tour: List of vertices in the prizes map Returns: Total prize of the tour From 73a25e81e9f65d72e2b32daa0ff6aaf72cc29abc Mon Sep 17 00:00:00 2001 From: PatrickOHara Date: Fri, 7 Jul 2023 16:58:22 +0100 Subject: [PATCH 03/10] updated black formatter --- requirements.txt | 6 +++--- tspwplib/utils.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6628435..f74a681 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ -black>=22.6.0 +black>=23.3.0 markdown-include>=0.6.0 mkdocs>=1.1.2 mkdocstrings[python]>=0.19.0 mkdocs-material>=6.0.2 -mypy>=0.971 -pylint>=2.14.5 +mypy>=1.4.1 +pylint>=-2.17.4 pytest>=6.1.1 pytest-tspwplib>=0.2.5 types-PyYAML>=6.0.1 \ No newline at end of file diff --git a/tspwplib/utils.py b/tspwplib/utils.py index 5c50834..99167fd 100644 --- a/tspwplib/utils.py +++ b/tspwplib/utils.py @@ -189,7 +189,7 @@ def adjacency_list_from_edge_list(edge_list: SimpleEdgeList) -> AdjList: Adjacency list representation """ adj_list: AdjList = {} - for (u, v) in edge_list: + for u, v in edge_list: if u in adj_list: adj_list[u].append(v) else: From c200b8ae21cdff53c5b0cc09193d55ac343fc1ff Mon Sep 17 00:00:00 2001 From: PatrickOHara Date: Thu, 10 Aug 2023 13:32:19 +0100 Subject: [PATCH 04/10] Get quota from alpha for londonaq --- tspwplib/problem.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/tspwplib/problem.py b/tspwplib/problem.py index 301d8f4..4fed191 100644 --- a/tspwplib/problem.py +++ b/tspwplib/problem.py @@ -472,6 +472,17 @@ def get_total_prize(self) -> Union[int, float]: return sum(self.demands.values()) return 0 + def get_quota(self, alpha: int) -> int: + """The quota is alpha percent of the total prize + + Args: + alpha: Percent of the total prize + + Returns: + quota + """ + return get_quota_from_alpha(alpha, self.get_total_prize()) + class ProfitsProblem(tsplib95.models.StandardProblem): """TSP with Profits Problem""" @@ -591,11 +602,7 @@ def get_quota(self, alpha: int) -> int: Returns: quota """ - if alpha > 100: - raise ValueError("Cannot have a percent over 100 for alpha") - if alpha < 0: - raise ValueError("Cannot have a negative percent for alpha") - return int(float(alpha * self.get_total_prize()) / 100.0) + return get_quota_from_alpha(alpha, self.get_total_prize()) def number_of_nodes(self) -> int: """Get the number of nodes in the problem @@ -670,6 +677,23 @@ def get_edges(self, normalize: bool = False) -> EdgeList: return list(super().get_edges()) +def get_quota_from_alpha(alpha: int, total_prize: int) -> int: + """The quota is alpha percent of the total prize + + Args: + alpha: Percent of the total prize + total_prize: Total prize of the graph + + Returns: + quota as an integer + """ + if alpha > 100: + raise ValueError("Cannot have a percent over 100 for alpha") + if alpha < 0: + raise ValueError("Cannot have a negative percent for alpha") + return int(float(alpha * total_prize) / 100.0) + + def is_pctsp_yes_instance( graph: nx.Graph, quota: int, root_vertex: Vertex, edge_list: EdgeList ) -> bool: From e26cb4ef471d5d6e7f8cdda859da5b711f2ca15d Mon Sep 17 00:00:00 2001 From: Patrick O'Hara Date: Wed, 16 Aug 2023 18:38:25 +0100 Subject: [PATCH 05/10] Imports --- tspwplib/__init__.py | 4 +++- tspwplib/problem.py | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tspwplib/__init__.py b/tspwplib/__init__.py index 70a8bac..7a2233f 100644 --- a/tspwplib/__init__.py +++ b/tspwplib/__init__.py @@ -21,12 +21,13 @@ from .exception import ( EdgesNotAdjacentException, EdgeNotFoundException, + NotConnectedException, NotSimpleException, NotSimpleCycleException, NotSimplePathException, ) from .metric import metricness, mst_cost, semi_mst_cost, uniform_random_cost -from .problem import BaseTSP, ProfitsProblem, is_pctsp_yes_instance +from .problem import BaseTSP, ProfitsProblem, get_quota_from_alpha, is_pctsp_yes_instance from .utils import ( build_path_to_londonaq_instance, build_path_to_londonaq_yaml, @@ -120,6 +121,7 @@ "edge_list_from_walk", "get_original_from_split_vertex", "get_original_path_from_split_path", + "get_quota_from_alpha", "head_prize", "is_complete", "is_complete_with_self_loops", diff --git a/tspwplib/problem.py b/tspwplib/problem.py index 4fed191..cebc6ae 100644 --- a/tspwplib/problem.py +++ b/tspwplib/problem.py @@ -52,24 +52,24 @@ class BaseTSP(pydantic.BaseModel): # pylint: disable=too-many-arguments - capacity: Optional[Union[int, float]] + capacity: Optional[Union[int, float]] = None comment: str demands: Optional[VertexFunction] depots: VertexList dimension: int - display_data: Optional[NodeCoords] + display_data: Optional[NodeCoords] = None display_data_type: DisplayDataType edge_data: SimpleEdgeList edge_data_format: EdgeDataFormat - edge_weights: Optional[SimpleEdgeFunction] + edge_weights: Optional[SimpleEdgeFunction] = None edge_weight_format: EdgeWeightFormat edge_weight_type: EdgeWeightType fixed_edges: SimpleEdgeList name: str - node_coords: Optional[NodeCoords] + node_coords: Optional[NodeCoords] = None node_coord_type: NodeCoordType problem_type: str - tours: Optional[List[VertexList]] + tours: Optional[List[VertexList]] = None class Config: """Pydantic configuration""" From e4da307ae5b9e65fd9ee0892aeead9c85ad5e9f2 Mon Sep 17 00:00:00 2001 From: Patrick O'Hara Date: Sat, 27 Jan 2024 18:08:14 +0000 Subject: [PATCH 06/10] Updating to python>=3.10 --- .github/workflows/tests.yml | 2 +- .pylintrc | 4 ++-- docs/installation.md | 2 +- requirements.txt | 16 ++++++++-------- setup.py | 14 +++++++------- tspwplib/__init__.py | 7 ++++++- tspwplib/converter.py | 1 - tspwplib/problem.py | 2 +- 8 files changed, 26 insertions(+), 22 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 055ba76..b058ae9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.10", "3.11", "3.12"] env: OPLIB_ROOT: ../OPLib diff --git a/.pylintrc b/.pylintrc index 10ed019..c1d3b84 100644 --- a/.pylintrc +++ b/.pylintrc @@ -388,8 +388,8 @@ preferred-modules= [EXCEPTIONS] # Exceptions that will emit a warning when caught. -overgeneral-exceptions=BaseException, - Exception +overgeneral-exceptions=builtins.BaseException, + builtins.Exception [REFACTORING] diff --git a/docs/installation.md b/docs/installation.md index 277f61e..d90459f 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -21,7 +21,7 @@ git clone https://github.com/rhgrant10/tsplib95.git It is convenient to define environment variables to define the location of OPLib and tsplib95: ```bash -TSPLIB_ROOT="$(pwd)/tsblib95/archives/problems/tsp" +TSPLIB_ROOT="$(pwd)/tsplib95/archives/problems/tsp" OPLIB_ROOT="$(pwd)/OPLib/" ``` diff --git a/requirements.txt b/requirements.txt index f74a681..6ec400a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ -black>=23.3.0 -markdown-include>=0.6.0 -mkdocs>=1.1.2 -mkdocstrings[python]>=0.19.0 -mkdocs-material>=6.0.2 -mypy>=1.4.1 -pylint>=-2.17.4 -pytest>=6.1.1 +black>=24.1.0 +markdown-include>=0.8.1 +mkdocs>=1.5.3 +mkdocstrings[python]>=0.24.0 +mkdocs-material>=9.5.5 +mypy>=1.8.0 +pylint>=-3.0.3 +pytest>=7.4.4 pytest-tspwplib>=0.2.5 types-PyYAML>=6.0.1 \ No newline at end of file diff --git a/setup.py b/setup.py index d37fdbb..54fbd6a 100644 --- a/setup.py +++ b/setup.py @@ -8,22 +8,22 @@ url="https://github.com/PatrickOHara/tspwplib", description="Library of instances for TSP with Profits", install_requires=[ - "networkx>=2.6.0", - "numpy>=1.21.0", - "pandas>=1.0.0", - "pydantic>=1.8.2", + "networkx>=3.2.1", + "numpy>=1.26.0", + "pandas>=2.0.0", + "pydantic>=2.5.3", "tsplib95>=0.7.1", ], name="tspwplib", packages=["tspwplib"], - python_requires=">=3.8", + python_requires=">=3.10", license="MIT", classifiers=[ "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3 :: Only", "Operating System :: OS Independent", ], diff --git a/tspwplib/__init__.py b/tspwplib/__init__.py index 7a2233f..348a3a6 100644 --- a/tspwplib/__init__.py +++ b/tspwplib/__init__.py @@ -27,7 +27,12 @@ NotSimplePathException, ) from .metric import metricness, mst_cost, semi_mst_cost, uniform_random_cost -from .problem import BaseTSP, ProfitsProblem, get_quota_from_alpha, is_pctsp_yes_instance +from .problem import ( + BaseTSP, + ProfitsProblem, + get_quota_from_alpha, + is_pctsp_yes_instance, +) from .utils import ( build_path_to_londonaq_instance, build_path_to_londonaq_yaml, diff --git a/tspwplib/converter.py b/tspwplib/converter.py index 6af5495..5dddb75 100644 --- a/tspwplib/converter.py +++ b/tspwplib/converter.py @@ -1,6 +1,5 @@ """Converting between different types of graphs""" - from copy import deepcopy import math from typing import Dict, List, Tuple, Union diff --git a/tspwplib/problem.py b/tspwplib/problem.py index cebc6ae..516d2d4 100644 --- a/tspwplib/problem.py +++ b/tspwplib/problem.py @@ -466,7 +466,7 @@ def get_root_vertex(self) -> Vertex: except KeyError as key_error: raise ValueError("The list of depots is empty") from key_error - def get_total_prize(self) -> Union[int, float]: + def get_total_prize(self) -> int: """ "Get the total prize (demand) of all vertices""" if self.demands: return sum(self.demands.values()) From 3c2c4fa573ad4d71eaff2cf82a5ab117bc355ae6 Mon Sep 17 00:00:00 2001 From: Patrick O'Hara Date: Sat, 27 Jan 2024 19:03:59 +0000 Subject: [PATCH 07/10] Install updated tsplib95 from fork --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 54fbd6a..a921646 100644 --- a/setup.py +++ b/setup.py @@ -8,11 +8,11 @@ url="https://github.com/PatrickOHara/tspwplib", description="Library of instances for TSP with Profits", install_requires=[ - "networkx>=3.2.1", + "networkx>=3.0.0", "numpy>=1.26.0", "pandas>=2.0.0", "pydantic>=2.5.3", - "tsplib95>=0.7.1", + "tsplib95@git+https://github.com/ben-hudson/tsplib95.git", ], name="tspwplib", packages=["tspwplib"], From 8f5e9c3bc6e6289a2c3d164a6eaf2ca0d8d827fd Mon Sep 17 00:00:00 2001 From: Patrick O'Hara Date: Mon, 29 Jan 2024 10:12:37 +0000 Subject: [PATCH 08/10] Upgrade docker python version --- .pylintrc | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index c1d3b84..56581ff 100644 --- a/.pylintrc +++ b/.pylintrc @@ -82,7 +82,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.8 +py-version=3.10 # Discover python modules and packages in the file system subtree. recursive=no diff --git a/Dockerfile b/Dockerfile index 9cfb7ed..a347f8d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.8 +FROM python:3.12 WORKDIR /app From ae557e11f27e5fa33ad84a13f171dcee176676ed Mon Sep 17 00:00:00 2001 From: Patrick O'Hara Date: Mon, 29 Jan 2024 10:30:40 +0000 Subject: [PATCH 09/10] Publish fix --- .github/workflows/publish.yml | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 563cb00..5240796 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,9 +10,13 @@ on: jobs: deploy: - + name: upload release to PyPI runs-on: ubuntu-latest - + # Specifying a GitHub environment is optional, but strongly encouraged + environment: release + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing + id-token: write steps: - uses: actions/checkout@v2 - name: Bump version and push tag @@ -23,18 +27,6 @@ jobs: DEFAULT_BUMP: patch REPO_OWNER: PatrickOHara RELEASE_BRANCHES: main - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools setuptools_scm wheel twine - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | - python setup.py sdist bdist_wheel - twine upload dist/* + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 From 42b45bd67ef022e39c825ca7305b9e9ef0403159 Mon Sep 17 00:00:00 2001 From: Patrick O'Hara Date: Mon, 29 Jan 2024 11:27:17 +0000 Subject: [PATCH 10/10] Refactor bump and publish --- .github/workflows/publish.yml | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5240796..45e3bf3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,14 +9,9 @@ on: - main jobs: - deploy: - name: upload release to PyPI + bump: + name: bump version runs-on: ubuntu-latest - # Specifying a GitHub environment is optional, but strongly encouraged - environment: release - permissions: - # IMPORTANT: this permission is mandatory for trusted publishing - id-token: write steps: - uses: actions/checkout@v2 - name: Bump version and push tag @@ -28,5 +23,16 @@ jobs: REPO_OWNER: PatrickOHara RELEASE_BRANCHES: main - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + pypi-publish: + name: upload release to PyPI + needs: bump + runs-on: ubuntu-latest + # Specifying a GitHub environment is optional, but strongly encouraged + environment: release + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing + id-token: write + steps: + # retrieve your distributions here + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1