You are on page 1of 53

Programming

in Artificial Intelligence
Marcus Gerhold (marcus.gerhold@gmail.com)

based on presentations by Ansgar Fehnker and Angelika Mader


Motivation – Tic Tac Toe
Content

 Recursion
 Minimax Algorithm
 Tic Tac Toe

Goal of this lecture:


 Provide you with sufficient material to work on TTT
Recursion
Recursion - recursive data structures

 In Java/Processing

class GridElement {
boolean visited;
boolean marked;
boolean wall_n, wall_e, wall_w,
wall_s;
int xcoord, ycoord;
GridElement north, east, west,
south;
GridElement parent;
}
Recursion - recursive data structures

 In C++
class ListElement { recursive data structures
are useful for
public: dynamic structures such as
ListElement(int); lists, trees, graphs,…
int getValue() const;
void setValue(int);
ListElement* getNext() const;
void setNext(ListElement *);

private:
int value;
ListElement *next;
};
Recursion - recursive functions
void ListElement::printList()
{
std::cout << value;
Note, that this
if (next != NULL) { This is
member
std::cout << " "; called
function calls
next->printList(); recursion.
itself.
}
else {
std::cout << std::endl;
}
}

NULL
Recursion

A recursive function is a function that calls itself, reducing


the problem a bit on each call:

void solveIt(the-Problem)
{
. . .
solveIt(the-Problem-a-bit-reduced);
}
Of course, there’s a lot more to it than this.

C++ for Everyone by Cay Horstmann


Copyright © 2012 by John Wiley & Sons. All rights reserved
Recursion

In recursion,
the same computation recurs,
or occurs repeatedly,
as the problem is solved.

But this is not looping!

C++ for Everyone by Cay Horstmann


Copyright © 2012 by John Wiley & Sons. All rights reserved
Recursion

Recursion is often the most natural way


of thinking about a problem,

and there are some computations


that are very difficult to perform without recursion.

C++ for Everyone by Cay Horstmann


Copyright © 2012 by John Wiley & Sons. All rights reserved
Recursion

Two keys requirements for a successful recursive function:


 Every recursive call must simplify the task in some way.
 There must be special cases to handle the simplest tasks directly
so that the function will stop calling itself.

C++ for Everyone by Cay Horstmann


Copyright © 2012 by John Wiley & Sons. All rights reserved
Exercise

For warming up a simple example: Factorial

 Iterative definition:
 6! = 1 ⋅ 2 ⋅ 3 ⋅ 4 ⋅ 5 ⋅ 6
 Recursive definition:
 6! = 6 ⋅ 5!
Exercise

For warming up a simple example: Factorial

 Iterative definition:
 n! = 1 ⋅ 2 ⋅ 3 ⋅ ... ⋅ n
 Recursive definition:
 n! = n ⋅ (n-1)! if n>1
 1! = 1;
Exercise

Iterative Recursive
for the smallest
int f_iterative(int n) { int f_recursive(int n){ instance of the
int result = 1; if (n <= 1) { problem we have to
return 1; give a solution.
for (int i = 1; i <= n; i++) }
{
result = result*i; return n * f_recursive(n - 1);
} }

return result;
} reduction to a
smaller problem
Recursion vs looping
Some vague rules of thumb:

Comparison on Recursion Iteration

Basic Function calls itself Set of instructions rep.


executed
Structure Contains set of instructions Contains initialization,
that reduces size of problem, increment, condition, set of
base condition, and calls to instructions, and a control
itself variable
Termination Base case in recursive Iteration until a condition is
function reached
Speed Slow(er) in execution Fast(er) in execution
Size of Code Recursion reduces size of Iteration makes code longer
code
Scopes Variables created in No stack
recursion are stored on stack
Recursion - recursive functions

 Call stack then the results are


brought upwards,
the open expressions
are evaluated and
again brought upwards,
etc...

first the recursive


calls go in the depth
until the level where
it terminates
Quiz

 This function is supposed to check if the number ends in number 8 (a


lucky number)
bool is_lucky(int number) {
int last_digit = number % 10;
if (last_digit == 8) {
return true;
} else {
// Test the number without the last digit
return is_lucky(number / 10);
}
}
 What is wrong with it?
Common Error: Infinite Recursion

Two key requirements for a successful recursive function:


 Every recursive call must simplify the task in some way.
 There must be special cases to handle the simplest tasks directly
so that the function will stop calling itself.

Failing to implement these requirements can lead to infinite


recursion (and very unpleasant consequences).

C++ for Everyone by Cay Horstmann


Copyright © 2012 by John Wiley & Sons. All rights reserved
Quiz

 What is mystery(4)?

int mystery(int n) {
if (n <= 1) {
return 1;
}
int result = mystery(n - 1);
return result + n * n;
}
You need prototypes
Mutual recursion bool odd(int);
bool even(int);
At least one

Even numbers Odd numbers

bool even(int number) { bool odd(int number) {


if (number == 1) { if (number == 1) {
return false; return true;
} else { } else {
return odd(number - 1); return even(number - 1);
} }
} }
Tree recursion – Multiple recursive calls

The depth first search algorithm recursively

Pseudocode

void DFS(Node current){


label current as visited;
for all unvisited successors successor of
current:
DFS(successor);
}
Tree recursion – Multiple recursive calls

The depth first search algorithm recursively

void DFS(Node current){


current.visited = true;
for (direction = 0; direction<4; direction++){
if ( !current->wall[direction]
&& !current->neighbour[direction]->visited){
DFS( current->neighbour);
}
}
Tree recursion – Multiple recursive calls

Merge sort
split

merge
Tree recursion – Multiple recursive calls

Merge sort
Pseudocode
merge_sort(list) {
if (the list is only one element)
return that list of one element
else {
split the list in two parts;
merge_sort(first part of the list);
merge_sort(second part of the list);
merge(the two sorted lists into one);
}
}
Recursion Classic - Towers of Hanoi

 Problem:
 move a tower of disks from pillar 1 to pillar 2
 only move one disk at a time
 only put a smaller disk on top of a higher
Recursion Classic - Towers of Hanoi

 Pseudo code
move_tower (int height, position from_A, position
to_B){
if (height==0) return; The legend mentions 64
else{ disks in a temple. If true,
move_tower (height-1, from_A, to_C); and moving a disk would
move_disc (from_A, to_B); take 1 second, it would
move_tower (height-1, from_C, to_B); take 585 billion years to
} finish
}
Recursion - Efficiency n=4

Fibonacci Numbers
n=1

n=2 n=5

n=3

...
Recursion - Efficiency

 Fibonacci Numbers
 Each value in the sequence is the sum of the two preceding
values.
 The first ten terms of the sequence are:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55,…
 Defined by equations
 f(1) = 1
 f(2) = 1
 f(n) = f(n-1)+f(n-2)
Recursion - Efficiency

 Fibonacci Numbers Seems to be inefficient.


 Straight forward solution: Try Fibonacci(40)

int fibonacci(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
Recursion - Efficiency

 Fibonacci Numbers
 Call graph of straight forward solution:
Lots of
unnecessary
repetitions
Recursion - Efficiency

 Fibonacci Numbers
 Better solution: This is close to the
iterative solution.
int subfib(int term, int val, int prev) {
if (term == 0) {
return prev; This solution uses so-
} called tail recursion.
if (term == 1) {
return val;
}
Outside of the scope of
return subfib(term - 1, val + prev, val);
this course.
}
int fib(int n) {
return subfib(n, 1, 0);
}
Recursion

Image taken from https://xkcd.com/


Tic Tac Toe
Tic Tac Toe
 represents
the player
 How to finish?

...

At this stage it is
easy to determine
who wins
How to almost finish

 has the turn


 Depends on who’s turn it is

If it is your
() turn, play
for win.

Assume the
best outcome
How to almost finish

has the turn


 Depends on who’s turn it is

The other
player also
plays to win.

Assume the
worst
outcome
Min Max Strategy Given a position, how
find the best move.
 has the turn

Choose to maximize
 turn own chances

Choose to
minimize
o turn opponents chances

Choose to maximize
own chances
 turn
Min Max Strategy How to evaluate the
moves?

How to evaluate
the other
 turn moves?

Easy if it’s the


o turn -1 end for o
-1
-1 for loss
0 for draw

Easy if it’s the


 turn +1 0 0 +1
end for x

+1 for win
0 for draw
How to do this
Min Max Strategy How to evaluate the
moves? recursively?

e !
km
Pic
 turn Maximize your
-1 -1 0 own score

o turn -1 +1 -1 0 0 +1 Minimize your


opponents score

 turn +1 0 0 +1
Maximize your
own score
Min Max Strategy

 Setting
 each board position determines a node
 there is an initial board position
 in each level there is one player to take the moves
 the possibilities of the game describe a tree
 each game is a path in the tree

 We assume that x is the player (and has the first move)


Min Max Strategy - Player x’s turn

 Pseudo Code
int maximise(Node node, int player) {
if (node is winning for player) return 1;
if (node is draw) return 0; mutual
if (node is loosing for player) return -1; recursion
int evaluation = -∞;
for all children child of the node :
evaluation = max(evaluation, minimise(child, other
player));
make the child successor if it has the max evaluation;
return evaluation;
}
Min Max Strategy - Player o’s turn

 Pseudo Code
int minimise(Node node, int player) {
if (node is winning for player) return -1;
if (node is draw) return 0; mutual
if (node is loosing for player) return +1; recursion
int evaluation = ∞;
for all children child of the node :
evaluation = min(evaluation, maximise(child, other
player));
make the child successor if it has the min evaluation;
return evaluation;
}
Min Max Strategy

maximize(...,1)

minimize(...,1)

maximize(...,1)
Min Max Strategy

maximize(...,1)

minimize(...,1)

maximize(...,1)

minimize(...,1)
Min Max Strategy

maximize(...,1)

minimize(...,1)

maximize(...,1)

minimize(...,1)
Min Max Strategy

maximize(...,1)

minimize(...,1)

maximize(...,
1)
Min Max Strategy

maximize(...,1)

minimize(...,1)

maximize(...,1)

minimize(...,1)
Min Max Strategy And so
on ...

maximize(...,1)

minimize(...,1)

maximize(...,1)

minimize(...,1)
Min Max Strategy – Simple recursive
Merged version
int minimax(Node node, int player, int maxPlayer) {
if the node is a terminal evaluate it and return evaluation
if (player is the maxPlayer) {
int evaluation = -∞;
for all children child of the node :
evaluation = max(evaluation, minimax(child, other player,
maxPlayer));
make the child successor if it has the max evaluation;
return evaluation;
}
else {
int evaluation = ∞;
for all children child of the node :
evaluation = min(evaluation, minimax(child, other player,
maxPlayer));
make the child successor if it has the min evaluation;
return evaluation;
}
} Two turns in one
Min Max Strategy
Addendum : Other 2p games

Example: Nim
● Multiple heaps of matches/objects
● 2 players take turns
● Remove as many as you want from one heap
● The one to remove the last match, wins
● Can you win, no matter what?
Addendum : Other 2p games
Admin

 Sign off on search asap


 Start on tic tac toe.
 Get help from the SA to find your way in the tic tac toe
framework

You might also like