aialgos 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.
- aialgos-0.1.0/PKG-INFO +179 -0
- aialgos-0.1.0/README.md +155 -0
- aialgos-0.1.0/aialgos/__init__.py +49 -0
- aialgos-0.1.0/aialgos/adversarial/__init__.py +170 -0
- aialgos-0.1.0/aialgos/ann/__init__.py +273 -0
- aialgos-0.1.0/aialgos/beyond_classical/__init__.py +214 -0
- aialgos-0.1.0/aialgos/csp/__init__.py +229 -0
- aialgos-0.1.0/aialgos/informed/__init__.py +107 -0
- aialgos-0.1.0/aialgos/uninformed/__init__.py +248 -0
- aialgos-0.1.0/aialgos.egg-info/PKG-INFO +179 -0
- aialgos-0.1.0/aialgos.egg-info/SOURCES.txt +13 -0
- aialgos-0.1.0/aialgos.egg-info/dependency_links.txt +1 -0
- aialgos-0.1.0/aialgos.egg-info/top_level.txt +1 -0
- aialgos-0.1.0/pyproject.toml +42 -0
- aialgos-0.1.0/setup.cfg +4 -0
aialgos-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aialgos
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Beginner-friendly AI search algorithms: BFS, DFS, A*, Minimax, CSP, ANN and more
|
|
5
|
+
Author-email: Qasim Alvi <qasimalvio685@email.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/mQasim04/aialgos
|
|
8
|
+
Project-URL: Repository, https://github.com/mQasim04/aialgos
|
|
9
|
+
Project-URL: Issues, https://github.com/mQasim04/aialgos/issues
|
|
10
|
+
Keywords: ai,artificial-intelligence,search,algorithms,bfs,dfs,a-star,minimax,csp,neural-network,machine-learning,education,beginners
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Education
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# aialgos 🤖
|
|
26
|
+
|
|
27
|
+
A **beginner-friendly** Python library covering the core AI algorithms taught in university courses.
|
|
28
|
+
|
|
29
|
+
**Zero dependencies** — pure Python, works everywhere.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install aialgos
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## What's inside?
|
|
38
|
+
|
|
39
|
+
| Module | Algorithms |
|
|
40
|
+
|--------|-----------|
|
|
41
|
+
| `uninformed` | BFS, DFS, DLS, UCS, Bidirectional BFS |
|
|
42
|
+
| `informed` | Greedy Best-First, A* |
|
|
43
|
+
| `adversarial` | Minimax, Alpha-Beta Pruning |
|
|
44
|
+
| `beyond_classical` | Hill Climbing, Steepest-Ascent HC, Simulated Annealing, Local Beam Search |
|
|
45
|
+
| `csp` | Backtracking, Forward Checking, MRV, LCV, Degree Heuristic |
|
|
46
|
+
| `ann` | Feedforward Neural Network (from scratch) |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
### Uninformed Search (BFS)
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from aialgos import bfs
|
|
56
|
+
|
|
57
|
+
graph = {
|
|
58
|
+
'A': ['B', 'C'],
|
|
59
|
+
'B': ['D', 'E'],
|
|
60
|
+
'C': ['F'],
|
|
61
|
+
'D': [], 'E': [], 'F': []
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
path = bfs(graph, start='A', goal='E')
|
|
65
|
+
print(path) # ['A', 'B', 'E']
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Informed Search (A*)
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from aialgos import a_star
|
|
72
|
+
|
|
73
|
+
graph = {
|
|
74
|
+
'A': [('B', 1), ('C', 4)],
|
|
75
|
+
'B': [('D', 5)],
|
|
76
|
+
'C': [('D', 1)],
|
|
77
|
+
'D': []
|
|
78
|
+
}
|
|
79
|
+
heuristic = {'A': 4, 'B': 3, 'C': 1, 'D': 0}
|
|
80
|
+
|
|
81
|
+
path, cost = a_star(graph, 'A', 'D', heuristic)
|
|
82
|
+
print(path, cost) # ['A', 'C', 'D'] 5
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Adversarial Search (Minimax)
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from aialgos import minimax
|
|
89
|
+
|
|
90
|
+
# Game tree as nested lists (leaf values: positive=MAX wins)
|
|
91
|
+
tree = {'A': ['B', 'C'], 'B': ['D', 'E'], 'C': ['F', 'G'],
|
|
92
|
+
'D': 3, 'E': 5, 'F': 2, 'G': 9}
|
|
93
|
+
|
|
94
|
+
def get_children(node):
|
|
95
|
+
v = tree[node]
|
|
96
|
+
return v if isinstance(v, list) else []
|
|
97
|
+
|
|
98
|
+
def evaluate(node):
|
|
99
|
+
v = tree[node]
|
|
100
|
+
return v if isinstance(v, int) else 0
|
|
101
|
+
|
|
102
|
+
score = minimax('A', depth=0, is_maximizing=True,
|
|
103
|
+
get_children=get_children, evaluate=evaluate, max_depth=2)
|
|
104
|
+
print(score) # 5
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Neural Network (ANN)
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from aialgos import NeuralNetwork
|
|
111
|
+
|
|
112
|
+
# Solve XOR problem
|
|
113
|
+
nn = NeuralNetwork([2, 4, 1], learning_rate=0.1)
|
|
114
|
+
|
|
115
|
+
X = [[0,0], [0,1], [1,0], [1,1]]
|
|
116
|
+
y = [[0], [1], [1], [0]]
|
|
117
|
+
|
|
118
|
+
nn.train(X, y, epochs=2000, print_every=500)
|
|
119
|
+
|
|
120
|
+
print(nn.predict([0, 1])) # ≈ [0.95]
|
|
121
|
+
print(nn.predict([0, 0])) # ≈ [0.05]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### CSP (Map Coloring)
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from aialgos import forward_checking
|
|
128
|
+
|
|
129
|
+
variables = ['WA', 'NT', 'SA', 'Q', 'NSW', 'V']
|
|
130
|
+
domains = {v: ['Red', 'Green', 'Blue'] for v in variables}
|
|
131
|
+
|
|
132
|
+
def diff(a, b): return a != b
|
|
133
|
+
|
|
134
|
+
constraints_map = {
|
|
135
|
+
'WA': [('NT', diff), ('SA', diff)],
|
|
136
|
+
'NT': [('WA', diff), ('SA', diff), ('Q', diff)],
|
|
137
|
+
'SA': [('WA', diff), ('NT', diff), ('Q', diff), ('NSW', diff), ('V', diff)],
|
|
138
|
+
'Q': [('NT', diff), ('SA', diff), ('NSW', diff)],
|
|
139
|
+
'NSW': [('Q', diff), ('SA', diff), ('V', diff)],
|
|
140
|
+
'V': [('SA', diff), ('NSW', diff)],
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
result = forward_checking(variables, domains, constraints_map)
|
|
144
|
+
print(result) # {'WA': 'Red', 'NT': 'Green', 'SA': 'Blue', ...}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Installation
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
pip install aialgos
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Or install from source:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
git clone https://github.com/mQasim04/aialgos
|
|
159
|
+
cd aialgos
|
|
160
|
+
pip install -e .
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Similar Libraries
|
|
166
|
+
|
|
167
|
+
| Library | Focus |
|
|
168
|
+
|---------|-------|
|
|
169
|
+
| `aima3` | Textbook algorithms (Russell & Norvig) - less beginner-friendly |
|
|
170
|
+
| `networkx` | Graph algorithms only |
|
|
171
|
+
| `python-constraint` | CSP only |
|
|
172
|
+
| `scikit-learn` | ML — no search algorithms |
|
|
173
|
+
| **aialgos** | All-in-one, beginner-focused, zero dependencies |
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT — free to use in education and projects.
|
aialgos-0.1.0/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# aialgos 🤖
|
|
2
|
+
|
|
3
|
+
A **beginner-friendly** Python library covering the core AI algorithms taught in university courses.
|
|
4
|
+
|
|
5
|
+
**Zero dependencies** — pure Python, works everywhere.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install aialgos
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What's inside?
|
|
14
|
+
|
|
15
|
+
| Module | Algorithms |
|
|
16
|
+
|--------|-----------|
|
|
17
|
+
| `uninformed` | BFS, DFS, DLS, UCS, Bidirectional BFS |
|
|
18
|
+
| `informed` | Greedy Best-First, A* |
|
|
19
|
+
| `adversarial` | Minimax, Alpha-Beta Pruning |
|
|
20
|
+
| `beyond_classical` | Hill Climbing, Steepest-Ascent HC, Simulated Annealing, Local Beam Search |
|
|
21
|
+
| `csp` | Backtracking, Forward Checking, MRV, LCV, Degree Heuristic |
|
|
22
|
+
| `ann` | Feedforward Neural Network (from scratch) |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### Uninformed Search (BFS)
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from aialgos import bfs
|
|
32
|
+
|
|
33
|
+
graph = {
|
|
34
|
+
'A': ['B', 'C'],
|
|
35
|
+
'B': ['D', 'E'],
|
|
36
|
+
'C': ['F'],
|
|
37
|
+
'D': [], 'E': [], 'F': []
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
path = bfs(graph, start='A', goal='E')
|
|
41
|
+
print(path) # ['A', 'B', 'E']
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Informed Search (A*)
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from aialgos import a_star
|
|
48
|
+
|
|
49
|
+
graph = {
|
|
50
|
+
'A': [('B', 1), ('C', 4)],
|
|
51
|
+
'B': [('D', 5)],
|
|
52
|
+
'C': [('D', 1)],
|
|
53
|
+
'D': []
|
|
54
|
+
}
|
|
55
|
+
heuristic = {'A': 4, 'B': 3, 'C': 1, 'D': 0}
|
|
56
|
+
|
|
57
|
+
path, cost = a_star(graph, 'A', 'D', heuristic)
|
|
58
|
+
print(path, cost) # ['A', 'C', 'D'] 5
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Adversarial Search (Minimax)
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from aialgos import minimax
|
|
65
|
+
|
|
66
|
+
# Game tree as nested lists (leaf values: positive=MAX wins)
|
|
67
|
+
tree = {'A': ['B', 'C'], 'B': ['D', 'E'], 'C': ['F', 'G'],
|
|
68
|
+
'D': 3, 'E': 5, 'F': 2, 'G': 9}
|
|
69
|
+
|
|
70
|
+
def get_children(node):
|
|
71
|
+
v = tree[node]
|
|
72
|
+
return v if isinstance(v, list) else []
|
|
73
|
+
|
|
74
|
+
def evaluate(node):
|
|
75
|
+
v = tree[node]
|
|
76
|
+
return v if isinstance(v, int) else 0
|
|
77
|
+
|
|
78
|
+
score = minimax('A', depth=0, is_maximizing=True,
|
|
79
|
+
get_children=get_children, evaluate=evaluate, max_depth=2)
|
|
80
|
+
print(score) # 5
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Neural Network (ANN)
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from aialgos import NeuralNetwork
|
|
87
|
+
|
|
88
|
+
# Solve XOR problem
|
|
89
|
+
nn = NeuralNetwork([2, 4, 1], learning_rate=0.1)
|
|
90
|
+
|
|
91
|
+
X = [[0,0], [0,1], [1,0], [1,1]]
|
|
92
|
+
y = [[0], [1], [1], [0]]
|
|
93
|
+
|
|
94
|
+
nn.train(X, y, epochs=2000, print_every=500)
|
|
95
|
+
|
|
96
|
+
print(nn.predict([0, 1])) # ≈ [0.95]
|
|
97
|
+
print(nn.predict([0, 0])) # ≈ [0.05]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### CSP (Map Coloring)
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from aialgos import forward_checking
|
|
104
|
+
|
|
105
|
+
variables = ['WA', 'NT', 'SA', 'Q', 'NSW', 'V']
|
|
106
|
+
domains = {v: ['Red', 'Green', 'Blue'] for v in variables}
|
|
107
|
+
|
|
108
|
+
def diff(a, b): return a != b
|
|
109
|
+
|
|
110
|
+
constraints_map = {
|
|
111
|
+
'WA': [('NT', diff), ('SA', diff)],
|
|
112
|
+
'NT': [('WA', diff), ('SA', diff), ('Q', diff)],
|
|
113
|
+
'SA': [('WA', diff), ('NT', diff), ('Q', diff), ('NSW', diff), ('V', diff)],
|
|
114
|
+
'Q': [('NT', diff), ('SA', diff), ('NSW', diff)],
|
|
115
|
+
'NSW': [('Q', diff), ('SA', diff), ('V', diff)],
|
|
116
|
+
'V': [('SA', diff), ('NSW', diff)],
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
result = forward_checking(variables, domains, constraints_map)
|
|
120
|
+
print(result) # {'WA': 'Red', 'NT': 'Green', 'SA': 'Blue', ...}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Installation
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pip install aialgos
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Or install from source:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
git clone https://github.com/mQasim04/aialgos
|
|
135
|
+
cd aialgos
|
|
136
|
+
pip install -e .
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Similar Libraries
|
|
142
|
+
|
|
143
|
+
| Library | Focus |
|
|
144
|
+
|---------|-------|
|
|
145
|
+
| `aima3` | Textbook algorithms (Russell & Norvig) - less beginner-friendly |
|
|
146
|
+
| `networkx` | Graph algorithms only |
|
|
147
|
+
| `python-constraint` | CSP only |
|
|
148
|
+
| `scikit-learn` | ML — no search algorithms |
|
|
149
|
+
| **aialgos** | All-in-one, beginner-focused, zero dependencies |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT — free to use in education and projects.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""
|
|
2
|
+
aialgos - A beginner-friendly AI algorithms library
|
|
3
|
+
====================================================
|
|
4
|
+
Topics covered:
|
|
5
|
+
- Uninformed Searches (BFS, DFS, DLS, UCS, Bidirectional)
|
|
6
|
+
- Informed Searches (Greedy Best-First, A*)
|
|
7
|
+
- Adversarial Searches (Minimax, Alpha-Beta Pruning)
|
|
8
|
+
- Beyond Classical Searches (Hill Climbing, Simulated Annealing, LBS)
|
|
9
|
+
- CSP (Backtracking, Forward Checking, MRV, LCV, Degree Heuristic)
|
|
10
|
+
- ANN (Artificial Neural Networks)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from aialgos.uninformed import bfs, dfs, dls, ucs, bidirectional_bfs
|
|
14
|
+
from aialgos.informed import greedy_best_first, a_star
|
|
15
|
+
from aialgos.adversarial import minimax, alpha_beta_pruning
|
|
16
|
+
from aialgos.beyond_classical import (
|
|
17
|
+
hill_climbing,
|
|
18
|
+
steepest_ascent_hill_climbing,
|
|
19
|
+
simulated_annealing,
|
|
20
|
+
local_beam_search,
|
|
21
|
+
)
|
|
22
|
+
from aialgos.csp import (
|
|
23
|
+
backtracking_search,
|
|
24
|
+
forward_checking,
|
|
25
|
+
select_mrv,
|
|
26
|
+
order_lcv,
|
|
27
|
+
degree_heuristic,
|
|
28
|
+
)
|
|
29
|
+
from aialgos.ann import NeuralNetwork
|
|
30
|
+
|
|
31
|
+
__version__ = "0.1.0"
|
|
32
|
+
__author__ = "Muhammad Qasim Alvi"
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
# Uninformed
|
|
36
|
+
"bfs", "dfs", "dls", "ucs", "bidirectional_bfs",
|
|
37
|
+
# Informed
|
|
38
|
+
"greedy_best_first", "a_star",
|
|
39
|
+
# Adversarial
|
|
40
|
+
"minimax", "alpha_beta_pruning",
|
|
41
|
+
# Beyond Classical
|
|
42
|
+
"hill_climbing", "steepest_ascent_hill_climbing",
|
|
43
|
+
"simulated_annealing", "local_beam_search",
|
|
44
|
+
# CSP
|
|
45
|
+
"backtracking_search", "forward_checking",
|
|
46
|
+
"select_mrv", "order_lcv", "degree_heuristic",
|
|
47
|
+
# ANN
|
|
48
|
+
"NeuralNetwork",
|
|
49
|
+
]
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Adversarial Search Algorithms
|
|
3
|
+
===============================
|
|
4
|
+
Used in two-player zero-sum games (like Tic-Tac-Toe, Chess).
|
|
5
|
+
One player tries to MAXIMIZE score, the other tries to MINIMIZE it.
|
|
6
|
+
|
|
7
|
+
Algorithms:
|
|
8
|
+
- Minimax
|
|
9
|
+
- Alpha-Beta Pruning (faster Minimax)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def minimax(state, depth, is_maximizing, get_children, evaluate, max_depth):
|
|
14
|
+
"""
|
|
15
|
+
Minimax Algorithm
|
|
16
|
+
-----------------
|
|
17
|
+
The MAX player picks the move with the highest score.
|
|
18
|
+
The MIN player picks the move with the lowest score.
|
|
19
|
+
Explores the full game tree up to max_depth.
|
|
20
|
+
|
|
21
|
+
Parameters:
|
|
22
|
+
state : Current game state (any format — board, dict, etc.)
|
|
23
|
+
depth (int): Current depth in the game tree (start with 0).
|
|
24
|
+
is_maximizing (bool): True if current player is the maximizer.
|
|
25
|
+
get_children (callable): Function(state) → list of child states.
|
|
26
|
+
evaluate (callable): Function(state) → numeric score.
|
|
27
|
+
Positive = good for MAX, negative = good for MIN.
|
|
28
|
+
max_depth (int): How many levels deep to search.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
int: The best score achievable from this state.
|
|
32
|
+
|
|
33
|
+
Example (Tic-Tac-Toe style):
|
|
34
|
+
>>> # See examples/adversarial_example.py for a full game demo
|
|
35
|
+
>>> def get_children(state): return [state + [i] for i in range(3)]
|
|
36
|
+
>>> def evaluate(state): return len(state) % 2 # dummy eval
|
|
37
|
+
>>> minimax([], 0, True, get_children, evaluate, max_depth=2)
|
|
38
|
+
1
|
|
39
|
+
"""
|
|
40
|
+
# Base case: reached depth limit or terminal state
|
|
41
|
+
if depth == max_depth or not get_children(state):
|
|
42
|
+
return evaluate(state)
|
|
43
|
+
|
|
44
|
+
if is_maximizing:
|
|
45
|
+
best = float('-inf')
|
|
46
|
+
for child in get_children(state):
|
|
47
|
+
score = minimax(child, depth + 1, False, get_children, evaluate, max_depth)
|
|
48
|
+
best = max(best, score)
|
|
49
|
+
return best
|
|
50
|
+
else:
|
|
51
|
+
best = float('inf')
|
|
52
|
+
for child in get_children(state):
|
|
53
|
+
score = minimax(child, depth + 1, True, get_children, evaluate, max_depth)
|
|
54
|
+
best = min(best, score)
|
|
55
|
+
return best
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def minimax_best_move(state, get_children, evaluate, max_depth):
|
|
59
|
+
"""
|
|
60
|
+
Find the best move using Minimax (for the maximizing player).
|
|
61
|
+
|
|
62
|
+
Parameters:
|
|
63
|
+
state : Current game state.
|
|
64
|
+
get_children (callable): Function(state) → list of child states.
|
|
65
|
+
evaluate (callable): Function(state) → numeric score.
|
|
66
|
+
max_depth (int): How many levels deep to search.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The child state (move) with the best minimax score.
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
>>> # See examples/adversarial_example.py for Tic-Tac-Toe demo
|
|
73
|
+
"""
|
|
74
|
+
best_score = float('-inf')
|
|
75
|
+
best_child = None
|
|
76
|
+
|
|
77
|
+
for child in get_children(state):
|
|
78
|
+
score = minimax(child, 1, False, get_children, evaluate, max_depth)
|
|
79
|
+
if score > best_score:
|
|
80
|
+
best_score = score
|
|
81
|
+
best_child = child
|
|
82
|
+
|
|
83
|
+
return best_child
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def alpha_beta_pruning(state, depth, alpha, beta, is_maximizing,
|
|
87
|
+
get_children, evaluate, max_depth):
|
|
88
|
+
"""
|
|
89
|
+
Alpha-Beta Pruning
|
|
90
|
+
------------------
|
|
91
|
+
An optimized version of Minimax. Skips branches that cannot
|
|
92
|
+
affect the final decision — often searches TWICE AS DEEP in the
|
|
93
|
+
same time as plain Minimax.
|
|
94
|
+
|
|
95
|
+
alpha = best score MAX can guarantee so far (starts at -inf)
|
|
96
|
+
beta = best score MIN can guarantee so far (starts at +inf)
|
|
97
|
+
If alpha >= beta, prune (stop exploring that branch).
|
|
98
|
+
|
|
99
|
+
Parameters:
|
|
100
|
+
state : Current game state.
|
|
101
|
+
depth (int): Current depth (start with 0).
|
|
102
|
+
alpha (float): Alpha value (start with float('-inf')).
|
|
103
|
+
beta (float): Beta value (start with float('inf')).
|
|
104
|
+
is_maximizing (bool): True if current player is the maximizer.
|
|
105
|
+
get_children (callable): Function(state) → list of child states.
|
|
106
|
+
evaluate (callable): Function(state) → numeric score.
|
|
107
|
+
max_depth (int): How many levels deep to search.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
int: Best achievable score.
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
>>> score = alpha_beta_pruning(
|
|
114
|
+
... state=[], depth=0,
|
|
115
|
+
... alpha=float('-inf'), beta=float('inf'),
|
|
116
|
+
... is_maximizing=True,
|
|
117
|
+
... get_children=lambda s: [s+[i] for i in range(3)],
|
|
118
|
+
... evaluate=lambda s: len(s) % 2,
|
|
119
|
+
... max_depth=2
|
|
120
|
+
... )
|
|
121
|
+
"""
|
|
122
|
+
if depth == max_depth or not get_children(state):
|
|
123
|
+
return evaluate(state)
|
|
124
|
+
|
|
125
|
+
if is_maximizing:
|
|
126
|
+
value = float('-inf')
|
|
127
|
+
for child in get_children(state):
|
|
128
|
+
score = alpha_beta_pruning(child, depth + 1, alpha, beta,
|
|
129
|
+
False, get_children, evaluate, max_depth)
|
|
130
|
+
value = max(value, score)
|
|
131
|
+
alpha = max(alpha, value)
|
|
132
|
+
if beta <= alpha:
|
|
133
|
+
break # Beta cutoff — MIN won't allow this branch
|
|
134
|
+
return value
|
|
135
|
+
else:
|
|
136
|
+
value = float('inf')
|
|
137
|
+
for child in get_children(state):
|
|
138
|
+
score = alpha_beta_pruning(child, depth + 1, alpha, beta,
|
|
139
|
+
True, get_children, evaluate, max_depth)
|
|
140
|
+
value = min(value, score)
|
|
141
|
+
beta = min(beta, value)
|
|
142
|
+
if beta <= alpha:
|
|
143
|
+
break # Alpha cutoff — MAX won't allow this branch
|
|
144
|
+
return value
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def alpha_beta_best_move(state, get_children, evaluate, max_depth):
|
|
148
|
+
"""
|
|
149
|
+
Find the best move using Alpha-Beta Pruning (for the maximizer).
|
|
150
|
+
|
|
151
|
+
Parameters:
|
|
152
|
+
state : Current game state.
|
|
153
|
+
get_children (callable): Function(state) → list of child states.
|
|
154
|
+
evaluate (callable): Function(state) → numeric score.
|
|
155
|
+
max_depth (int): How many levels deep to search.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
The child state (move) with the best alpha-beta score.
|
|
159
|
+
"""
|
|
160
|
+
best_score = float('-inf')
|
|
161
|
+
best_child = None
|
|
162
|
+
|
|
163
|
+
for child in get_children(state):
|
|
164
|
+
score = alpha_beta_pruning(child, 1, float('-inf'), float('inf'),
|
|
165
|
+
False, get_children, evaluate, max_depth)
|
|
166
|
+
if score > best_score:
|
|
167
|
+
best_score = score
|
|
168
|
+
best_child = child
|
|
169
|
+
|
|
170
|
+
return best_child
|