|
9 | 9 | "This notebook serves as supporting material for topics covered in **Chapter 5 - Adversarial Search** in the book *Artificial Intelligence: A Modern Approach.* This notebook uses implementations from [games.py](https://github.com/aimacode/aima-python/blob/master/games.py) module. Let's import required classes, methods, global variables etc., from games module." |
10 | 10 | ] |
11 | 11 | }, |
| 12 | + { |
| 13 | + "cell_type": "markdown", |
| 14 | + "metadata": {}, |
| 15 | + "source": [ |
| 16 | + "# Contents\n", |
| 17 | + "\n", |
| 18 | + "* Game Representation\n", |
| 19 | + "* Game Examples\n", |
| 20 | + " * Tic-Tac-Toe\n", |
| 21 | + " * Figure 5.2 Game\n", |
| 22 | + "* Min-Max\n", |
| 23 | + "* Players\n", |
| 24 | + "* Let's Play Some Games!" |
| 25 | + ] |
| 26 | + }, |
12 | 27 | { |
13 | 28 | "cell_type": "code", |
14 | 29 | "execution_count": 1, |
|
200 | 215 | }, |
201 | 216 | { |
202 | 217 | "cell_type": "code", |
203 | | - "execution_count": 6, |
| 218 | + "execution_count": 4, |
204 | 219 | "metadata": { |
205 | 220 | "collapsed": true |
206 | 221 | }, |
|
225 | 240 | }, |
226 | 241 | { |
227 | 242 | "cell_type": "code", |
228 | | - "execution_count": 7, |
| 243 | + "execution_count": 5, |
229 | 244 | "metadata": {}, |
230 | 245 | "outputs": [ |
231 | 246 | { |
|
249 | 264 | }, |
250 | 265 | { |
251 | 266 | "cell_type": "code", |
252 | | - "execution_count": 9, |
| 267 | + "execution_count": 6, |
253 | 268 | "metadata": { |
254 | 269 | "collapsed": true |
255 | 270 | }, |
|
267 | 282 | }, |
268 | 283 | { |
269 | 284 | "cell_type": "code", |
270 | | - "execution_count": 10, |
| 285 | + "execution_count": 7, |
271 | 286 | "metadata": { |
272 | 287 | "collapsed": true |
273 | 288 | }, |
|
278 | 293 | }, |
279 | 294 | { |
280 | 295 | "cell_type": "code", |
281 | | - "execution_count": 11, |
| 296 | + "execution_count": 8, |
282 | 297 | "metadata": {}, |
283 | 298 | "outputs": [ |
284 | 299 | { |
|
302 | 317 | }, |
303 | 318 | { |
304 | 319 | "cell_type": "code", |
305 | | - "execution_count": 12, |
| 320 | + "execution_count": 9, |
306 | 321 | "metadata": { |
307 | 322 | "collapsed": true |
308 | 323 | }, |
|
313 | 328 | }, |
314 | 329 | { |
315 | 330 | "cell_type": "code", |
316 | | - "execution_count": 13, |
| 331 | + "execution_count": 10, |
317 | 332 | "metadata": {}, |
318 | 333 | "outputs": [ |
319 | 334 | { |
|
337 | 352 | }, |
338 | 353 | { |
339 | 354 | "cell_type": "code", |
340 | | - "execution_count": 14, |
| 355 | + "execution_count": 11, |
341 | 356 | "metadata": { |
342 | 357 | "collapsed": true |
343 | 358 | }, |
|
348 | 363 | }, |
349 | 364 | { |
350 | 365 | "cell_type": "code", |
351 | | - "execution_count": 15, |
| 366 | + "execution_count": 12, |
352 | 367 | "metadata": {}, |
353 | 368 | "outputs": [ |
354 | 369 | { |
|
372 | 387 | }, |
373 | 388 | { |
374 | 389 | "cell_type": "code", |
375 | | - "execution_count": 16, |
| 390 | + "execution_count": 13, |
376 | 391 | "metadata": { |
377 | 392 | "collapsed": true |
378 | 393 | }, |
|
383 | 398 | }, |
384 | 399 | { |
385 | 400 | "cell_type": "code", |
386 | | - "execution_count": 17, |
| 401 | + "execution_count": 14, |
387 | 402 | "metadata": {}, |
388 | 403 | "outputs": [ |
389 | 404 | { |
|
407 | 422 | }, |
408 | 423 | { |
409 | 424 | "cell_type": "code", |
410 | | - "execution_count": 18, |
| 425 | + "execution_count": 15, |
411 | 426 | "metadata": { |
412 | 427 | "collapsed": true |
413 | 428 | }, |
|
418 | 433 | }, |
419 | 434 | { |
420 | 435 | "cell_type": "code", |
421 | | - "execution_count": 19, |
| 436 | + "execution_count": 16, |
422 | 437 | "metadata": {}, |
423 | 438 | "outputs": [ |
424 | 439 | { |
|
442 | 457 | }, |
443 | 458 | { |
444 | 459 | "cell_type": "code", |
445 | | - "execution_count": 20, |
| 460 | + "execution_count": 17, |
446 | 461 | "metadata": { |
447 | 462 | "collapsed": true |
448 | 463 | }, |
|
451 | 466 | "%psource Fig52Game" |
452 | 467 | ] |
453 | 468 | }, |
| 469 | + { |
| 470 | + "cell_type": "markdown", |
| 471 | + "metadata": {}, |
| 472 | + "source": [ |
| 473 | + "# MIN-MAX\n", |
| 474 | + "\n", |
| 475 | + "This algorithm (often called *Minimax*) computes the next move for a player (MIN or MAX) at their current state. It recursively computes the minimax value of successor states, until it reaches terminals (the leaves of the tree). Using the `utility` value of the terminal states, it computes the values of parent states until it reaches the initial node (the root of the tree). The algorithm returns the move that returns the optimal value of the initial node's successor states.\n", |
| 476 | + "\n", |
| 477 | + "Below is the code for the algorithm:" |
| 478 | + ] |
| 479 | + }, |
| 480 | + { |
| 481 | + "cell_type": "code", |
| 482 | + "execution_count": 18, |
| 483 | + "metadata": { |
| 484 | + "collapsed": true |
| 485 | + }, |
| 486 | + "outputs": [], |
| 487 | + "source": [ |
| 488 | + "%psource minimax_decision" |
| 489 | + ] |
| 490 | + }, |
| 491 | + { |
| 492 | + "cell_type": "markdown", |
| 493 | + "metadata": {}, |
| 494 | + "source": [ |
| 495 | + "We will now play the Fig52 game using this algorithm. Take a look at the Fig52Game from above to follow along.\n", |
| 496 | + "\n", |
| 497 | + "It is the turn of MAX to move, and he is at state A. He can move to B, C or D, using moves a1, a2 and a3 respectively. MAX's goal is to maximize the end value. So, to make a decision, MAX needs to know the values at the aforementioned nodes and pick the greatest one. After MAX, it is MIN's turn to play. So MAX wants to know what will the values of B, C and D be after MIN plays.\n", |
| 498 | + "\n", |
| 499 | + "The problem then becomes what move will MIN make at B, C and D. The successor states of all these nodes are terminal states, so MIN will pick the smallest value for each node. So, for B he will pick 3 (from move b1), for C he will pick 2 (from move c1) and for D he will again pick 2 (from move d3).\n", |
| 500 | + "\n", |
| 501 | + "Let's see this in code:" |
| 502 | + ] |
| 503 | + }, |
| 504 | + { |
| 505 | + "cell_type": "code", |
| 506 | + "execution_count": 19, |
| 507 | + "metadata": {}, |
| 508 | + "outputs": [ |
| 509 | + { |
| 510 | + "name": "stdout", |
| 511 | + "output_type": "stream", |
| 512 | + "text": [ |
| 513 | + "b1\n", |
| 514 | + "c1\n", |
| 515 | + "d3\n" |
| 516 | + ] |
| 517 | + } |
| 518 | + ], |
| 519 | + "source": [ |
| 520 | + "print(minimax_decision('B', fig52))\n", |
| 521 | + "print(minimax_decision('C', fig52))\n", |
| 522 | + "print(minimax_decision('D', fig52))" |
| 523 | + ] |
| 524 | + }, |
| 525 | + { |
| 526 | + "cell_type": "markdown", |
| 527 | + "metadata": {}, |
| 528 | + "source": [ |
| 529 | + "Now MAX knows that the values for B, C and D are 3, 2 and 2 (produced by the above moves of MIN). The greatest is 3, which he will get with move a1. This is then the move MAX will make. Let's see the algorithm in full action:" |
| 530 | + ] |
| 531 | + }, |
| 532 | + { |
| 533 | + "cell_type": "code", |
| 534 | + "execution_count": 20, |
| 535 | + "metadata": {}, |
| 536 | + "outputs": [ |
| 537 | + { |
| 538 | + "name": "stdout", |
| 539 | + "output_type": "stream", |
| 540 | + "text": [ |
| 541 | + "a1\n" |
| 542 | + ] |
| 543 | + } |
| 544 | + ], |
| 545 | + "source": [ |
| 546 | + "print(minimax_decision('A', fig52))" |
| 547 | + ] |
| 548 | + }, |
454 | 549 | { |
455 | 550 | "cell_type": "markdown", |
456 | 551 | "metadata": {}, |
|
0 commit comments