62
"Intelligent" CS 5 An object is structured data that is alive, responsible, and intelligent. Sound too friendly? This week’s objects and classes will be just the opposite ... X to move. Is there a way to win? | | | | | | | | | | | | | | | | | | | | | | | | | | | |X| | | | | |X| |X|O| | | |X|O|O|O|X|O| | --------------- 0 1 2 3 4 5 6 Hw 10 due 11/15 EXAM 2 Mon/Tue

"Intelligent" CS 5 An object is structured data that is alive, responsible, and intelligent. Sound too friendly? This week’s objects and classes will be

Embed Size (px)

Citation preview

"Intelligent" CS 5

An object is structured data that is alive, responsible, and intelligent.

Sound too friendly?

This week’s objects and classes will be just the opposite ...

X to move.

Is there a way to win?

| | | | | | | || | | | | | | || | | | | | | || | | |X| | | || |X| |X|O| | ||X|O|O|O|X|O| |--------------- 0 1 2 3 4 5 6

Hw 10 due 11/15EXAM 2Mon/Tue

def tomorrow(self): """Changes the calling object so that it represents one calendar day after the date it originally represented. """ if self.month in [1,3,5,7,8,10] and self.day == 31: self.day = 0 self.month += 1 elif self.month in [4,6,9,11] and self.day == 30: self.day = 0 self.month += 1 elif self.month == 2: if self.isLeapYear() and self.day == 29: self.day = 0 self.month += 1 elif (self.isLeapYear() == False) and self.day == 28: self.day = 0 self.month += 1 elif self.month == 12 and self.day == 31: self.day = 0 self.month = 1 self.year += 1 self.day += 1

Coding Style

def tomorrow(self): """Changes the calling object so that it represents one calendar day after the date it originally represented. """ DIM = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if self.isLeapYear() == True: DIM = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] self.day += 1 if self.day > DIM[self.month]: self.day = 1 self.month += 1 if self.month > 12: self.month = 1 self.year += 1 else: self.day += 1 if self.day > DIM[self.month]: self.day = 1 self.month += 1 if self.month > 12: self.month = 1 self.year += 1

Better Style, But...

def tomorrow(self): """Changes the calling object so that it represents one calendar day after the date it originally represented. """ DIM = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if self.isLeapYear(): DIM[2] = 29 self.day += 1 if self.day > DIM[self.month]: self.day = 1 self.month += 1 if self.month > 12: self.month = 1 self.year += 1

An Elegant Solution

isBefore/isAfter

def isBefore(self, d2): """ Returns true if self is before d2 """ if self.year < d2.year: return True if self.month < d2.month and self.year == d2.year: return True if self.day < d2.day and d2.month == self.month and \ self.year == d2.year: return True return False

def isAfter(self, d2): """ Returns true if self is after d2 """ if self.year > d2.year: return True if self.month > d2.month and self.year == d2.year: return True if self.day > d2.day and d2.month == self.month and \ self.year == d2.year: return True return False

An Elegant Solution

def isBefore(self, d2): """ Returns true if self is before d2 """ if self.year < d2.year: return True if self.month < d2.month and self.year == d2.year: return True if self.day < d2.day and d2.month == self.month and \ self.year == d2.year: return True return False

def isAfter(self, d2): """ Returns true if self is after d2 """ return d2.isBefore(self)

Another Elegant Solution

def isBefore(self, d2): """ Returns true if self is before d2 """ return ([self.year, self.month, self.day] < [d2.year, d2.month, d2.day])

def isAfter(self, d2): """ Returns true if self is after d2 """ return d2.isBefore(self)

diff

def diff( self, d2 ): """ Returns the number of days between self and d2 """ dcopy = self.copy() difference = 0 if dcopy.isBefore(d2) == True: while dcopy.isBefore(d2) == True: dcopy.tomorrow() difference -= 1 else: while dcopy.isAfter(d2): dcopy.yesterday() difference += 1 return difference

An Elegant Solution

def diff( self, d2 ): """ Returns the number of days between self and d2 """ dcopy = self.copy() difference = 0 while dcopy.isBefore(d2): dcopy.tomorrow() difference -= 1 while dcopy.isAfter(d2): dcopy.yesterday() difference += 1 return difference

Aargh!

Python has no Connect-four datatype…

| | | | | | | || | | | | | | || | | | | | | || | | |X| | | || |X| |X|O| | ||X|O|O|O|X| |O|--------------- 0 1 2 3 4 5 6

Can I see a demo?

… but we can correct that!

Designing classes

1) What data? (Data Members)

2) What are objects' crucial capabilities? (Methods)

Not limited to 7x6!

Connect Four: the object b

Boardb

intwidthstr str str

str str str

str str str

datalist str

str

str

data

intheight

What is the name of the method that will construct this data?

Connect Four: constructor

class Board: """ a datatype representing a C4 board with an arbitrary number of rows and cols """ def __init__( self, width, height ): """ the constructor for objects of type Board """ self.width = width self.height = height self.data = [] # this will be the board for row in range( 6 ): boardRow = [] for col in range( 7 ): boardRow += [' '] # add a space to this row self.data += [boardRow]

Bad magic?

Connect Four: the object b

Boardb

intwidthstr str str

str str str

str str str

datalist str

str

str

intheight

| | | | | | | || | | | | | | || | | | | | | || | | |X| | | || |X| |X|O| | ||X|O|O|O|X| |O|--------------- 0 1 2 3 4 5 6

What is the name of the method that will print this data?

def __repr__(self): """ this method returns a string representation for an object of type Board """ s = '' for row in range( 6 ): s += '|' for col in range( 7 ): s += self.data[row][col] + '|' s += '\n'

return s

Connect Four: __repr__

To change?

To add?

which row is row 0, row 1, and so on?

"Quiz"class Board: def allowsMove(self, col):

def addMove(self, col, ox): for row in range( self.height ): if self.data[row][col] != ' ': self.data[row-1][col] = ox self.data[self.height-1][col] = ox

Step through this addMove method.

What is each line doing?

How many problems are there?

a C4 board col # 'X' or 'O'

Write allowsMove to return True if col is a valid move;

False otherwise.

NAME:

C4 Board class: methods

__init__( self, width, height )

allowsMove( self, col )

__repr__( self )

addMove( self, col, ox )

isFull( self )

winsFor( self, ox )

the “constructor”

checks if allowed

places a checker

outputs a string

checks if any space is left

checks if a player has won

hostGame( self )play (person vs. person)!

delMove( self, col )removes a checker

Which of these will require the most thought?

winsFor( self, ox )

Thoughts?

X O

bb.winsFor( 'X' )or 'O'

corner cases?

Two-player games have been a key focus of AI as long as computers have been around…

Strategic thinking == intelligence?

In 1945, Alan Turing predicted that computers

would be better chess players than people in

~ 50 years…

and thus would have achieved intelligence.

Alan Turing memorial Manchester, England

Two-player games have been a key focus of AI as long as computers have been around…

Strategic thinking == intelligence?

… humans and computers have different relative strengths in these games.

humanscomputers

good at evaluating the strength of a board for a player

good at looking ahead in the game to find

winning combinations of moves

How humans play games…

- experts could reconstruct these perfectly - novice players did far worse…

An experiment (by A. deGroot) was performed in which chess positions were shown to novice and expert players…

How humans play games…

- experts could reconstruct these perfectly - novice players did far worse…

Random chess positions (not legal ones) were then shown to the two groups

- experts and novices did equally well (badly) at reconstructing them!

An experiment (by A. deGroot) was performed in which chess positions were shown to novice and expert players…

Two-player games have been a key focus of AI as long as computers have been around…

Strategic thinking == intelligence?

humanscomputers

good at evaluating the strength of a board for a player

good at looking ahead in the game to find

winning combinations of moves

… humans and computers have different relative strengths in these games.

building an AI chess playeremulating a human by

evaluating a board position

The Player class

PlayerpForX

Details(data and methods)

What data and methods are needed to construct and implement a Player object?

Let's see a demo!

stringox

Picture of a Player object

Player

PlayerpForX

__init__(self, ox, tbt, ply)

stringtbt

__repr__(self)

scoreBoard(self, b)

scoresFor(self, b)

tiebreakMove(self, scores)

nextMove(self, b)

oppCh(self)

'X' 'LEFT'intply

3

DATA

METHODS

tiebreakTypechecker, O or X

scoreBoard ‘X’‘O’

Assigns a score to any board, b

100.0 50.0 0.0A simple system:for a win for a lossfor anything else

Score for Score for

Score for Score for

scoreBoard

Assigns a score to any board, b

100.0 50.0 -1.0A simple system:for a win illegal boardfor anything else

scoreBoard(self, b)

Implementation ideas…

What methods that already exist will come in handy?

This doesn't seem to be looking very

far ahead !

How can there be no 'X' or 'O' input?

What class is this method in?

0.0for a loss

Looking further ahead…

scoreBoard looks ahead 0 movesThe "Zen" approach --

we are excellent at this!

If you look one move ahead, how many possibilities are there to consider?

0-ply

1-ply

A 1-ply lookahead player will "see" an impending victory.

to move…

A score for each

column…?

score

Looking further ahead…

scoreBoard looks ahead 0 movesThe "Zen" approach --

we are excellent at this!

If you look one move ahead, how many possibilities are there to consider?

0-ply

A 2-ply lookahead player will also "see"

an opponent's impending victory.

to move…

What about 3-ply? 2-ply

1-ply score

score

Looking further ahead…

scoreBoard looks ahead 0 movesThe "Zen" approach --

we are excellent at this!

If you look one move ahead, how many possibilities are there to consider?

0-ply

1-ply

scoresFor( self, b ) returns a LIST of scores, one for each column you can choose to move next…

2-ply

|O| | | | | | ||X| | | |O| |X||O| | | |X|O|X||X| | | |O|O|X||X| |X| |X|O|O||X| |O|O|O|X|X|--------------- 0 1 2 3 4 5 6

| | | | | | |O|| | | | | | |O|| | | | | | |X||X| |X|O| | |O||X|O|O|X| |X|X||X|O|O|O| |O|X|--------------- 0 1 2 3 4 5 6

It is O’s move. What scores does a 1-ply lookahead for O assign to each move?

col 0 col 1 col 2 col 3 col 4 col 5 col 6

It is X’s move. What scores does a 2-ply lookahead for X assign to each move?

col 0 col 1 col 2 col 3 col 4 col 5 col 6

Which change at 3-ply?

Which change at 2-ply?

Example 1-ply and 2-ply lookahead scores

b

0-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

1-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

2-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

3-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

Practice ‘X’‘O’

0-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

1-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

2-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

3-ply scores for O:col 0 col 1 col 2 col 3 col 4 col 5 col 6

Solutions

-1

-1

-1

-1

50 50 50 50 50 50

50 50 100

50 50 50

0

0

100

100

0

0

0 0 50

100

00

b ‘X’‘O’

500

1200

2000

2800

Computer Chess

early programs ~ 1960’s

Computers cut their teeth playing chess…

Ranking

beginner

amateur

world ranked

world champion

MacHack (1100) ~ 1967 MIT

Deep Thought ~ 1989 Carnegie Mellon

Slate (2070) ~ 1970’s Northwestern

Deep Blue ~ 1996 IBM

Deep Blue rematch ~ 1997 IBM

100’s of moves/sec

10,000’s of moves/sec

1,000,000’s moves/sec

3,500,000 moves/secDeep Fritz: 2002X3D Fritz: 2003 Hydra: 2006

200,000,000 moves/sec

first paper: 1950

What is Hydra's chess rating?

Games’ Branching Factors

Branching Factor Estimatesfor different two-player games

Tic-tac-toe 4

Connect Four 7

Checkers 10

Othello 30

Chess 40

Go 300

• On average, there are fewer than 40 possible moves that a chess player can make from any board configuration… 0 Ply

1 Ply

2 Ply

Hydra at home in the United Arab Emirates…

Hydra looks ahead 18 ply !

Games’ Branching Factors

Branching Factor Estimatesfor different two-player games

Tic-tac-toe 4

Connect Four 7

Checkers 10

Othello 30

Chess 40

Go 300

1 Ply

2 Ply

Boundaries for qualitatively

different games…

0 Ply

Games’ Branching Factors

Branching Factor Estimatesfor different two-player games

Tic-tac-toe 4

Connect Four 7

Checkers 10

Othello 30

Chess 40

Go 300

“solved” games

computer-dominated

human-dominated

1 Ply

2 Ply

0 Ply

Progress

‘X’‘O’new‘X’

Col 6

Col 5

Col 4Col 3Col 2

Col 1

Col 0

b

scoresFor each column

(1) For each possible move

(2) Add it to the board

‘X’‘O’new‘X’

Col 6

Col 5

Col 4Col 3Col 2

Col 1

Col 0

b(1) For each possible move

(2) Add it to the board

(3) Ask OPPONENT to score each board

At what ply?

0.0

50.0

50.0

0.00.0

50.0

0.0

scoresFor each column

‘X’‘O’new‘X’

Col 6

Col 5

Col 4Col 3Col 2

Col 1

Col 0

b(1) For each possible move

(2) Add it to the board

(3) Ask OPPONENT to score each board

(4) Take the opponent's MAX

0.0

50.0

0.00.0

50.0

0.0

What to assign for a score?

scoresFor each column

50.0

scoresFor

def scoresFor(self, b):

(1) For each possible move

(2) Add it to the board

(3) Ask OPPONENT to score each board - at ? ply

(4) the score is 100-max

Write tiebreakMove to return the leftmost best score

inside the list scores

def tiebreakMove(self, scores):

if self.tbt == 'LEFT':

How would 'RANDOM' and 'RIGHT' work differently?

hw11 this week

• Problem 3: A Connect Four Player…

• Extra: scoreBoard4Tourney and a CS 5 C4 round-robin

http://www.stanford.edu/~ccecka/research/C4.html

Using more scores than 0, 50, and 100 !

• Problem 2: A Connect Four Board…

don't give this board a 50.0 !

“Quiz” Names:

|O| | | | | | ||X| | | |O| |X||O| | | |X|O|X||X| | | |O|O|X||X| |X| |X|O|O||X| |O|O|O|X|X|--------------- 0 1 2 3 4 5 6

| | | | | | |O|| | | | | | |O|| | | | | | |X||X| |X|O| | |O||X|O|O|X| |X|X||X|O|O|O| |O|X|--------------- 0 1 2 3 4 5 6

It is O’s move. What scores does a 1-ply lookahead for O assign to each move?

col 0 col 1 col 2 col 3 col 4 col 5 col 6

It is X’s move. What scores does a 2-ply lookahead for X assign to each move?

col 0 col 1 col 2 col 3 col 4 col 5 col 6

be careful!

-1 100

50 100

50 100

50

100

0 0 0 50 0 -1

Which change at 2-ply? 0 0

Which change at 3-ply?0

|O| | | | | | ||X| | | |O| |X||O| | | |X|O|X||X| | | |O|O|X||X| |X| |X|O|O||X| |O|O|O|X|X|--------------- 0 1 2 3 4 5 6

It is O’s move. What scores does a 1-ply lookahead for O assign to each move?

col 0 col 1 col 2 col 3 col 4 col 5 col 6

Which change at 2-ply?

Looking further ahead …

0 ply:

2 ply: 3 ply:

Zen choice of move: here and now

| | | | | | | || | | | | | | ||O| | | | | | ||X| | | | | | ||X|O|O| | |X| ||O|X|X|O|X|O| |--------------- 0 1 2 3 4 5 6

| | | | | | | || | | | | | | || | | | |X| | || | | | |O|O| || |X|X| |X|O| ||O|X|O| |O|X| |--------------- 0 1 2 3 4 5 6

(1) Player will win

(2) Player will avoid losing

(3) Player will set up a win by forcing the

opponent to avoid losing

X’s move X‘s move

1 ply:

| | | | | | | || | | | | | | || | | | | | | || | | | | | | || |O|X| | | | ||O|X|X|X| |O|O|--------------- 0 1 2 3 4 5 6

X’s move

‘X’‘O’new‘X’

Col 6

Col 5

Col 4Col 3Col 2

Col 1

Col 0

b

Choosing the best move

(1) For each possible move

(2) Add it to the board

(3) Ask OPPONENT to score each board - ply?

(4) Reverse the scores

100.0

50.0

50.0

100.0100.0

50.0

100.0

‘X’‘O’new‘X’

Col 6

Col 5

Col 4Col 3Col 2

Col 1

Col 0

b

Choosing the best move

100.0

50.0

50.0

100.0100.0

50.0

100.0

(1) For each possible move

(2) Add it to the board

(3) Ask OPPONENT to score each board - ply?

(4) Reverse the scores

(5) Find one max - that's it!

Connect Four

| | | | | | | || | | | | | | || | | | | | | || | | |X| | | || |X| |X|O| | ||X|O|O|O|X| |O|--------------- 0 1 2 3 4 5 6

Suppose our Board class's 2d list of lists is named self.data. What is

the name of this single spot?

For your convenience, the creators of Python’s library have included a Board class that can represent any size of Connect Four board... !

Connect Four: the object b

This is true for sufficiently broad definitions of “the creators of Python’s library” ...

Boardb

def addMove(self, col, player)

intNROWS

intNCOLS

def allowsMove(self, col)

char char char

char char char

char char char

datalist char

char

char

def winsFor(self, player)

data members

methods

What is player ?

Connect Four: the object b

This is true for sufficiently broad definitions of “the creators of Python’s library” ...

Boardb

def addMove(self, col, player)

intNROWS

intNCOLS

def allowsMove(self, col)

char char char

char char char

char char char

datalist char

char

char

def winsFor(self, player)

data members

methods

Which methods will alter b? Which leave it alone?

Connect Four: Board

Starting code for the Board class

class Board: def __init__( self, numRows, numCols ): """ our Board's constructor """ self.NROWS = numRows self.NCOLS = numCols self.data = [] for r in range(self.NROWS): onerow = [' ']*self.NCOLS self.data += [onerow]

def __repr__(self): """ thoughts? """

look familiar?

Connect Four: Boardclass Board: def __init__( self, numRows, numCols ): """ our Board's constructor """ self.NROWS = numRows self.NCOLS = numCols self.data = [] for r in range(self.NR): onerow = [' ']*self.NC self.data += [onerow]

def __repr__(self): """ thoughts? """ s = '\n' for r in range(self.NROWS): s += '|' for c in range(self.NCOLS): s += self.data[r][c] + '|'

return s

look familiar?

a bit more to go !

Problem 2

class Board

__init__

allowsMove

__repr__

addMove

isFull

winsFor

the “constructor”

checks if allowed

places a checker

outputs to screen

checks if space left

checks if a player has won

Hw11 Pr2: Connect Four Board

hostGame play!

What's trickiest here?

Problem 2

class Board

__init__

allowsMove

__repr__

addMove

isFull

winsFor

the “constructor”

checks if allowed

places a checker

outputs to screen

checks if space left

checks if a player has won

Hw11 Pr2: Connect Four Board

hostGame play!

What's trickiest here?

What's wrong here?

| | | | | | | || | | | | | | || | | | | | | || | | |O|O| | ||X|X| |O|X|X|X||X|O|O|O|O|X|X|--------------- 0 1 2 3 4 5 6

def winsForHoriz(self, player): inarow = 0

for r in range(self.NROWS): for c in range(self.NCOLS):

if self.data[r][c] == player: inarow += 1 else: inarow = 0

if inarow == 4: return True

return False

Strategies?

horizontals

verticals

diagonals ??| | | | | | | || | | | | | | || | | | | | | || | | |O|O| | ||X|X| |O|X|X|X||X|O|O|O|O|X|X|--------------- 0 1 2 3 4 5 6

“Quiz”class Board{ # __init__ and __repr__ methods here… # 3 data members: # self.NR == number of rows # self.NC == number of cols # self.data == the 2d list of lists of chars

def mysteryMethod(self, col, ox): r = 0 while r < self.NR and self.data[r][col] == ' ': r += 1 self.data[r-1][col] = ox

def allowsMove(self, col):

}

Briefly, what is each line of the mysteryMethod doing?

Which method is it?

Write allowsMove to return whether the input col is a valid column to move.

(True or False)

1

2

3

Could it go wrong?

Problem 2

class Board

__init__

allowsMove

__repr__

addMove

isFull

winsFor

the “constructor”

checks if allowed

places a checker

outputs to screen

checks if space left

checks if a player has won

Hw11 Pr2: Connect Four Board

hostGame play!

What's trickiest here?

Problem 2

class Board

__init__

allowsMove

__repr__

addMove

isFull

winsFor

the “constructor”

checks if allowed

places a checker

outputs to screen

checks if space left

checks if a player has won

Hw11 Pr2: Connect Four Board

hostGame play!

What's trickiest here?

Strategies?

horizontals

verticals

diagonals ??| | | | | | | || | | | | | | || | | | | | | || | | |X| | | || |X| |X|O| | ||X|O|O|O|O| |O|--------------- 0 1 2 3 4 5 6