search-library 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. search_library-0.1.0/.github/workflows/cd.yml +63 -0
  2. search_library-0.1.0/.github/workflows/ci.yml +68 -0
  3. search_library-0.1.0/.gitignore +42 -0
  4. search_library-0.1.0/.python-version +1 -0
  5. search_library-0.1.0/CHANGELOG.md +33 -0
  6. search_library-0.1.0/LICENSE +21 -0
  7. search_library-0.1.0/PKG-INFO +209 -0
  8. search_library-0.1.0/README.md +180 -0
  9. search_library-0.1.0/pyproject.toml +109 -0
  10. search_library-0.1.0/src/search_library/__init__.py +21 -0
  11. search_library-0.1.0/src/search_library/algorithms/__init__.py +5 -0
  12. search_library-0.1.0/src/search_library/algorithms/astar.py +126 -0
  13. search_library-0.1.0/src/search_library/core/__init__.py +13 -0
  14. search_library-0.1.0/src/search_library/core/nodes.py +57 -0
  15. search_library-0.1.0/src/search_library/core/problem.py +65 -0
  16. search_library-0.1.0/src/search_library/core/result.py +37 -0
  17. search_library-0.1.0/src/search_library/core/state.py +22 -0
  18. search_library-0.1.0/src/search_library/exceptions/__init__.py +17 -0
  19. search_library-0.1.0/src/search_library/exceptions/exceptions.py +63 -0
  20. search_library-0.1.0/src/search_library/graph/__init__.py +6 -0
  21. search_library-0.1.0/src/search_library/graph/edges.py +37 -0
  22. search_library-0.1.0/src/search_library/graph/graph.py +192 -0
  23. search_library-0.1.0/src/search_library/grid/__init__.py +6 -0
  24. search_library-0.1.0/src/search_library/grid/grid.py +228 -0
  25. search_library-0.1.0/src/search_library/grid/grid_search.py +79 -0
  26. search_library-0.1.0/src/search_library/heuristics/__init__.py +11 -0
  27. search_library-0.1.0/src/search_library/heuristics/base.py +43 -0
  28. search_library-0.1.0/src/search_library/heuristics/euclidean.py +34 -0
  29. search_library-0.1.0/src/search_library/heuristics/manhattan.py +29 -0
  30. search_library-0.1.0/src/search_library/py.typed +0 -0
  31. search_library-0.1.0/src/search_library/utils/__init__.py +1 -0
  32. search_library-0.1.0/src/search_library/utils/helpers.py +44 -0
  33. search_library-0.1.0/tests/__init__.py +1 -0
  34. search_library-0.1.0/tests/test_core.py +93 -0
  35. search_library-0.1.0/tests/test_exceptions.py +60 -0
  36. search_library-0.1.0/tests/test_graph.py +195 -0
  37. search_library-0.1.0/tests/test_grid.py +274 -0
  38. search_library-0.1.0/tests/test_heuristics.py +74 -0
  39. search_library-0.1.0/tests/test_utils.py +54 -0
@@ -0,0 +1,63 @@
1
+ name: CD
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ ci:
14
+ uses: ./.github/workflows/ci.yml
15
+ permissions:
16
+ contents: read
17
+
18
+ release:
19
+ needs: ci
20
+ runs-on: ubuntu-latest
21
+ concurrency:
22
+ group: release
23
+ cancel-in-progress: false
24
+
25
+ permissions:
26
+ contents: write
27
+ id-token: write
28
+
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 0
33
+ token: ${{ secrets.GITHUB_TOKEN }}
34
+
35
+ - name: Install uv
36
+ uses: astral-sh/setup-uv@v4
37
+ with:
38
+ version: "latest"
39
+
40
+ - name: Set up Python
41
+ run: uv python install 3.11
42
+
43
+ - name: Install dependencies
44
+ run: uv sync
45
+
46
+ - name: Python Semantic Release
47
+ id: semantic
48
+ uses: python-semantic-release/python-semantic-release@v9
49
+ with:
50
+ github_token: ${{ secrets.GITHUB_TOKEN }}
51
+
52
+ - name: Publish to PyPI
53
+ if: steps.semantic.outputs.released == 'true'
54
+ uses: pypa/gh-action-pypi-publish@release/v1
55
+ with:
56
+ attestations: true
57
+
58
+ - name: Publish GitHub Release
59
+ if: steps.semantic.outputs.released == 'true'
60
+ uses: python-semantic-release/publish-action@v9
61
+ with:
62
+ github_token: ${{ secrets.GITHUB_TOKEN }}
63
+ tag: ${{ steps.semantic.outputs.tag }}
@@ -0,0 +1,68 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_call:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ lint-and-type-check:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v4
21
+ with:
22
+ version: "latest"
23
+
24
+ - name: Set up Python 3.11
25
+ run: uv python install 3.11
26
+
27
+ - name: Install dependencies
28
+ run: uv sync
29
+
30
+ - name: Run Ruff linting
31
+ run: uv run ruff check src/ tests/
32
+
33
+ - name: Run Ruff formatting check
34
+ run: uv run ruff format --check src/ tests/
35
+
36
+ - name: Run MyPy type checking
37
+ run: uv run mypy src/
38
+
39
+ test:
40
+ runs-on: ubuntu-latest
41
+ strategy:
42
+ matrix:
43
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
44
+ fail-fast: false
45
+
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+
49
+ - name: Install uv
50
+ uses: astral-sh/setup-uv@v4
51
+ with:
52
+ version: "latest"
53
+
54
+ - name: Set up Python ${{ matrix.python-version }}
55
+ run: uv python install ${{ matrix.python-version }}
56
+
57
+ - name: Install dependencies
58
+ run: uv sync --python ${{ matrix.python-version }}
59
+
60
+ - name: Run tests with coverage
61
+ run: uv run pytest --cov=search_library --cov-report=xml --cov-report=term-missing --cov-fail-under=90
62
+
63
+ - name: Upload coverage report
64
+ if: matrix.python-version == '3.11'
65
+ uses: actions/upload-artifact@v4
66
+ with:
67
+ name: coverage-report
68
+ path: coverage.xml
@@ -0,0 +1,42 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info/
8
+ *.egg
9
+
10
+ # Virtual environments
11
+ .venv/
12
+ venv/
13
+ env/
14
+
15
+ # IDE
16
+ .idea/
17
+ .vscode/
18
+ *.swp
19
+ *.swo
20
+
21
+ # Testing & Coverage
22
+ htmlcov/
23
+ .coverage
24
+ .coverage.*
25
+ coverage.xml
26
+ *.cover
27
+ .pytest_cache/
28
+ .mypy_cache/
29
+
30
+ # Distribution / Packaging
31
+ *.whl
32
+ *.tar.gz
33
+
34
+ # UV
35
+ uv.lock
36
+
37
+ # OS
38
+ .DS_Store
39
+ Thumbs.db
40
+
41
+ # Ruff
42
+ .ruff_cache/
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,33 @@
1
+ # CHANGELOG
2
+
3
+
4
+ ## v0.1.0 (2026-06-20)
5
+
6
+ ### Bug Fixes
7
+
8
+ - Formatting for grid.py and add workflow_call trigger to CI
9
+ ([`8d75c31`](https://github.com/ahincho/search-library/commit/8d75c314464b2b2090786a66ae4c3785c839d0d1))
10
+
11
+ - Use pip+build instead of uv in semantic-release container
12
+ ([`a740379`](https://github.com/ahincho/search-library/commit/a74037961a15263a40bc9b86740afb2f25a9d6a7))
13
+
14
+ ### Chores
15
+
16
+ - Add workflow_dispatch trigger to CD for manual releases
17
+ ([`15c5bb0`](https://github.com/ahincho/search-library/commit/15c5bb020e562d4ea9906c190cffacde2a321349))
18
+
19
+ ### Documentation
20
+
21
+ - Improve README with badges, examples, architecture and roadmap
22
+ ([`e6e21ab`](https://github.com/ahincho/search-library/commit/e6e21abd928097180bd5ad6b1f81c2820a7f9fb6))
23
+
24
+ ### Features
25
+
26
+ - Initial implementation of search-library with A* algorithm - Core abstractions: Node, State,
27
+ SearchProblem, SearchResult - A* search algorithm with heapq priority queue (f=g+h) - Heuristics:
28
+ Manhattan, Euclidean, extensible base ABC - Graph support: weighted directed/undirected graphs -
29
+ Grid support: 2D pathfinding with obstacles, 4/8 directions - Custom exceptions and utility
30
+ helpers - Full test suite (92 tests, 98.87% coverage) - Ruff + MyPy strict configuration - CI/CD:
31
+ GitHub Actions (matrix 3.11-3.14) + semantic-release + PyPI - pyproject.toml with complete PyPI
32
+ metadata (MIT license)
33
+ ([`ae2c4e7`](https://github.com/ahincho/search-library/commit/ae2c4e794f1312e2297237ce0ebd3093908b8fc4))
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 ahincho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,209 @@
1
+ Metadata-Version: 2.4
2
+ Name: search-library
3
+ Version: 0.1.0
4
+ Summary: A professional, extensible search algorithm framework for discrete spaces (graphs and grids). Implements A* with pluggable heuristics.
5
+ Project-URL: Homepage, https://github.com/ahincho/search-library
6
+ Project-URL: Repository, https://github.com/ahincho/search-library
7
+ Project-URL: Issues, https://github.com/ahincho/search-library/issues
8
+ Project-URL: Documentation, https://github.com/ahincho/search-library#readme
9
+ Author-email: ahincho <ahincho@unsa.edu.pe>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: a-star,algorithm,astar,graph,grid,heuristic,pathfinding,search
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.11
28
+ Description-Content-Type: text/markdown
29
+
30
+ # search-library
31
+
32
+ [![CI](https://github.com/ahincho/search-library/actions/workflows/ci.yml/badge.svg)](https://github.com/ahincho/search-library/actions/workflows/ci.yml)
33
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
34
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
35
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
36
+ [![MyPy](https://img.shields.io/badge/type--checked-mypy-blue.svg)](http://mypy-lang.org/)
37
+ [![Coverage](https://img.shields.io/badge/coverage-98%25-brightgreen.svg)]()
38
+
39
+ A professional, extensible search algorithm framework for discrete spaces (graphs and 2D grids).
40
+
41
+ ## Features
42
+
43
+ - **A\* Search Algorithm** — optimal pathfinding with `f(n) = g(n) + h(n)`
44
+ - **Graph support** — weighted directed/undirected graphs with adjacency lists
45
+ - **Grid support** — 2D pathfinding with obstacles, variable costs, 4/8-directional movement
46
+ - **Pluggable heuristics** — Manhattan, Euclidean, or bring your own
47
+ - **Extensible architecture** — designed for adding BFS, DFS, Dijkstra without modifying base code
48
+ - **Strict typing** — full `mypy --strict` compliance with Generics and Protocols
49
+ - **Zero runtime dependencies** — pure Python standard library only
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ pip install search-library
55
+ ```
56
+
57
+ Or with uv:
58
+
59
+ ```bash
60
+ uv add search-library
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ### Graph Search
66
+
67
+ ```python
68
+ from search_library import Graph, AStarSearch
69
+
70
+ # Create an undirected weighted graph
71
+ graph = Graph[str](directed=False)
72
+ graph.add_edge("A", "B", 1.0)
73
+ graph.add_edge("B", "C", 2.0)
74
+ graph.add_edge("A", "C", 5.0)
75
+
76
+ # Solve with A*
77
+ problem = graph.to_search_problem("A", "C")
78
+ solver = AStarSearch(problem)
79
+ result = solver.search()
80
+
81
+ print(result.path) # ['A', 'B', 'C']
82
+ print(result.total_cost) # 3.0
83
+ print(result.nodes_explored) # 3
84
+ ```
85
+
86
+ ### Grid Pathfinding (Maze)
87
+
88
+ ```python
89
+ from search_library import Grid, AStarSearch
90
+ from search_library.grid import GridSearchProblem
91
+
92
+ # 0 = walkable, 1 = obstacle
93
+ matrix = [
94
+ [0, 0, 0, 0, 0],
95
+ [0, 1, 1, 1, 0],
96
+ [0, 0, 0, 1, 0],
97
+ [0, 1, 0, 0, 0],
98
+ [0, 0, 0, 0, 0],
99
+ ]
100
+
101
+ grid = Grid.from_matrix(matrix)
102
+ problem = GridSearchProblem(grid, start=(0, 0), goal=(4, 4))
103
+ solver = AStarSearch(problem)
104
+ result = solver.search()
105
+
106
+ print(result.success) # True
107
+ print(result.total_cost) # 8.0
108
+ print(result.nodes_explored) # Number of states explored
109
+ ```
110
+
111
+ ### Custom Heuristic
112
+
113
+ ```python
114
+ from search_library.heuristics.base import Heuristic
115
+
116
+ class ChebyshevHeuristic(Heuristic[tuple[int, int]]):
117
+ """Chebyshev distance — useful for 8-directional grids."""
118
+ def estimate(self, state: tuple[int, int], goal: tuple[int, int]) -> float:
119
+ return float(max(abs(state[0] - goal[0]), abs(state[1] - goal[1])))
120
+ ```
121
+
122
+ ### Custom Search Problem
123
+
124
+ ```python
125
+ from search_library.core.problem import SearchProblem
126
+ from search_library.algorithms.astar import AStarSearch
127
+
128
+ class EightPuzzle(SearchProblem[tuple[int, ...]]):
129
+ """Example: define any discrete search problem."""
130
+ def initial_state(self) -> tuple[int, ...]:
131
+ return (1, 2, 3, 4, 0, 5, 6, 7, 8)
132
+
133
+ def is_goal(self, state: tuple[int, ...]) -> bool:
134
+ return state == (1, 2, 3, 4, 5, 6, 7, 8, 0)
135
+
136
+ def successors(self, state: tuple[int, ...]) -> list[tuple[tuple[int, ...], float]]:
137
+ # Return list of (next_state, cost) tuples
138
+ ...
139
+ ```
140
+
141
+ ## Architecture
142
+
143
+ ```
144
+ src/search_library/
145
+ ├── core/ # Node, State (Protocol), SearchProblem (ABC), SearchResult
146
+ ├── algorithms/ # A* implementation (extensible for BFS, DFS, Dijkstra)
147
+ ├── heuristics/ # Heuristic ABC + Manhattan + Euclidean
148
+ ├── graph/ # Graph + Edge + GraphSearchProblem adapter
149
+ ├── grid/ # Grid + GridSearchProblem adapter (4/8 directions)
150
+ ├── utils/ # Formatting helpers
151
+ └── exceptions/ # SearchError hierarchy
152
+ ```
153
+
154
+ ### Design Principles
155
+
156
+ - **SOLID** — each class has a single responsibility; open for extension, closed for modification
157
+ - **Strategy Pattern** — heuristics are interchangeable at runtime
158
+ - **Adapter Pattern** — Graph and Grid adapt to the unified SearchProblem interface
159
+ - **Generic Types** — algorithms work with any hashable state type
160
+
161
+ ## Development
162
+
163
+ ```bash
164
+ # Install all dependencies (including dev tools)
165
+ uv sync
166
+
167
+ # Run tests with coverage
168
+ uv run pytest
169
+
170
+ # Lint
171
+ uv run ruff check src/ tests/
172
+
173
+ # Format
174
+ uv run ruff format src/ tests/
175
+
176
+ # Type check (strict mode)
177
+ uv run mypy src/
178
+
179
+ # Build wheel + sdist
180
+ uv build
181
+ ```
182
+
183
+ ## CI/CD
184
+
185
+ | Pipeline | Trigger | What it does |
186
+ |----------|---------|--------------|
187
+ | **CI** | push, PR | Ruff + MyPy + Pytest (matrix: 3.11, 3.12, 3.13, 3.14) |
188
+ | **CD** | push to main | CI + Semantic Release + PyPI publish |
189
+
190
+ Versioning follows [Conventional Commits](https://www.conventionalcommits.org/):
191
+ - `feat:` → minor version bump
192
+ - `fix:` → patch version bump
193
+ - `feat!:` / `BREAKING CHANGE:` → major version bump
194
+
195
+ ## Roadmap
196
+
197
+ - [x] A* Search Algorithm
198
+ - [x] Manhattan & Euclidean heuristics
199
+ - [x] Graph support (directed/undirected, weighted)
200
+ - [x] Grid support (4/8 directions, obstacles)
201
+ - [ ] BFS (Breadth-First Search)
202
+ - [ ] DFS (Depth-First Search)
203
+ - [ ] Dijkstra's Algorithm
204
+ - [ ] Bidirectional Search
205
+ - [ ] Visualization utilities
206
+
207
+ ## License
208
+
209
+ [MIT](LICENSE) — free for academic and commercial use.
@@ -0,0 +1,180 @@
1
+ # search-library
2
+
3
+ [![CI](https://github.com/ahincho/search-library/actions/workflows/ci.yml/badge.svg)](https://github.com/ahincho/search-library/actions/workflows/ci.yml)
4
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
6
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
7
+ [![MyPy](https://img.shields.io/badge/type--checked-mypy-blue.svg)](http://mypy-lang.org/)
8
+ [![Coverage](https://img.shields.io/badge/coverage-98%25-brightgreen.svg)]()
9
+
10
+ A professional, extensible search algorithm framework for discrete spaces (graphs and 2D grids).
11
+
12
+ ## Features
13
+
14
+ - **A\* Search Algorithm** — optimal pathfinding with `f(n) = g(n) + h(n)`
15
+ - **Graph support** — weighted directed/undirected graphs with adjacency lists
16
+ - **Grid support** — 2D pathfinding with obstacles, variable costs, 4/8-directional movement
17
+ - **Pluggable heuristics** — Manhattan, Euclidean, or bring your own
18
+ - **Extensible architecture** — designed for adding BFS, DFS, Dijkstra without modifying base code
19
+ - **Strict typing** — full `mypy --strict` compliance with Generics and Protocols
20
+ - **Zero runtime dependencies** — pure Python standard library only
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ pip install search-library
26
+ ```
27
+
28
+ Or with uv:
29
+
30
+ ```bash
31
+ uv add search-library
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ### Graph Search
37
+
38
+ ```python
39
+ from search_library import Graph, AStarSearch
40
+
41
+ # Create an undirected weighted graph
42
+ graph = Graph[str](directed=False)
43
+ graph.add_edge("A", "B", 1.0)
44
+ graph.add_edge("B", "C", 2.0)
45
+ graph.add_edge("A", "C", 5.0)
46
+
47
+ # Solve with A*
48
+ problem = graph.to_search_problem("A", "C")
49
+ solver = AStarSearch(problem)
50
+ result = solver.search()
51
+
52
+ print(result.path) # ['A', 'B', 'C']
53
+ print(result.total_cost) # 3.0
54
+ print(result.nodes_explored) # 3
55
+ ```
56
+
57
+ ### Grid Pathfinding (Maze)
58
+
59
+ ```python
60
+ from search_library import Grid, AStarSearch
61
+ from search_library.grid import GridSearchProblem
62
+
63
+ # 0 = walkable, 1 = obstacle
64
+ matrix = [
65
+ [0, 0, 0, 0, 0],
66
+ [0, 1, 1, 1, 0],
67
+ [0, 0, 0, 1, 0],
68
+ [0, 1, 0, 0, 0],
69
+ [0, 0, 0, 0, 0],
70
+ ]
71
+
72
+ grid = Grid.from_matrix(matrix)
73
+ problem = GridSearchProblem(grid, start=(0, 0), goal=(4, 4))
74
+ solver = AStarSearch(problem)
75
+ result = solver.search()
76
+
77
+ print(result.success) # True
78
+ print(result.total_cost) # 8.0
79
+ print(result.nodes_explored) # Number of states explored
80
+ ```
81
+
82
+ ### Custom Heuristic
83
+
84
+ ```python
85
+ from search_library.heuristics.base import Heuristic
86
+
87
+ class ChebyshevHeuristic(Heuristic[tuple[int, int]]):
88
+ """Chebyshev distance — useful for 8-directional grids."""
89
+ def estimate(self, state: tuple[int, int], goal: tuple[int, int]) -> float:
90
+ return float(max(abs(state[0] - goal[0]), abs(state[1] - goal[1])))
91
+ ```
92
+
93
+ ### Custom Search Problem
94
+
95
+ ```python
96
+ from search_library.core.problem import SearchProblem
97
+ from search_library.algorithms.astar import AStarSearch
98
+
99
+ class EightPuzzle(SearchProblem[tuple[int, ...]]):
100
+ """Example: define any discrete search problem."""
101
+ def initial_state(self) -> tuple[int, ...]:
102
+ return (1, 2, 3, 4, 0, 5, 6, 7, 8)
103
+
104
+ def is_goal(self, state: tuple[int, ...]) -> bool:
105
+ return state == (1, 2, 3, 4, 5, 6, 7, 8, 0)
106
+
107
+ def successors(self, state: tuple[int, ...]) -> list[tuple[tuple[int, ...], float]]:
108
+ # Return list of (next_state, cost) tuples
109
+ ...
110
+ ```
111
+
112
+ ## Architecture
113
+
114
+ ```
115
+ src/search_library/
116
+ ├── core/ # Node, State (Protocol), SearchProblem (ABC), SearchResult
117
+ ├── algorithms/ # A* implementation (extensible for BFS, DFS, Dijkstra)
118
+ ├── heuristics/ # Heuristic ABC + Manhattan + Euclidean
119
+ ├── graph/ # Graph + Edge + GraphSearchProblem adapter
120
+ ├── grid/ # Grid + GridSearchProblem adapter (4/8 directions)
121
+ ├── utils/ # Formatting helpers
122
+ └── exceptions/ # SearchError hierarchy
123
+ ```
124
+
125
+ ### Design Principles
126
+
127
+ - **SOLID** — each class has a single responsibility; open for extension, closed for modification
128
+ - **Strategy Pattern** — heuristics are interchangeable at runtime
129
+ - **Adapter Pattern** — Graph and Grid adapt to the unified SearchProblem interface
130
+ - **Generic Types** — algorithms work with any hashable state type
131
+
132
+ ## Development
133
+
134
+ ```bash
135
+ # Install all dependencies (including dev tools)
136
+ uv sync
137
+
138
+ # Run tests with coverage
139
+ uv run pytest
140
+
141
+ # Lint
142
+ uv run ruff check src/ tests/
143
+
144
+ # Format
145
+ uv run ruff format src/ tests/
146
+
147
+ # Type check (strict mode)
148
+ uv run mypy src/
149
+
150
+ # Build wheel + sdist
151
+ uv build
152
+ ```
153
+
154
+ ## CI/CD
155
+
156
+ | Pipeline | Trigger | What it does |
157
+ |----------|---------|--------------|
158
+ | **CI** | push, PR | Ruff + MyPy + Pytest (matrix: 3.11, 3.12, 3.13, 3.14) |
159
+ | **CD** | push to main | CI + Semantic Release + PyPI publish |
160
+
161
+ Versioning follows [Conventional Commits](https://www.conventionalcommits.org/):
162
+ - `feat:` → minor version bump
163
+ - `fix:` → patch version bump
164
+ - `feat!:` / `BREAKING CHANGE:` → major version bump
165
+
166
+ ## Roadmap
167
+
168
+ - [x] A* Search Algorithm
169
+ - [x] Manhattan & Euclidean heuristics
170
+ - [x] Graph support (directed/undirected, weighted)
171
+ - [x] Grid support (4/8 directions, obstacles)
172
+ - [ ] BFS (Breadth-First Search)
173
+ - [ ] DFS (Depth-First Search)
174
+ - [ ] Dijkstra's Algorithm
175
+ - [ ] Bidirectional Search
176
+ - [ ] Visualization utilities
177
+
178
+ ## License
179
+
180
+ [MIT](LICENSE) — free for academic and commercial use.