Lecture 23: A Markov model of Baseball (2 days)

(previous, next)



Here is drawing of the state-transition digraph for the first batter in a half-inning (not very pretty, as drawn here, but hopefully, you can still follow the arrows).

[Show code]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python2

import scipy

class RandVariable():
    def __init__(self, weights):
        s = float(sum(weights))
        self.w = [ w/s for w in weights]
        self.n = len(self.w)
    def rand(self):
        rv = scipy.rand()
        i = self.n-1
        while rv > self.w[i] and 0 <= i:
            rv -= self.w[i]
            i -= 1
        assert 0 <= i
        return i

class Batter:
    def __init__(self):
        self.contact = False
        self.walk = False
        self.out = False
        self.strikes = 0
        self.balls = 0
        print "\t\tNew batter"
    def __str__(self):
        if self.out:
            return "Strike-out"
        if self.walk:
            return "Walk"
        if self.contact:
            return "Contact"
        s = str((self.balls, self.strikes))
        return s
    def copy(self):
        o = self.__class__()
        o.contact = self.contact
        o.out = self.out
        o.outs = self.outs
        o.walk = self.walk
        o.strikes = self.strikes
        o.balls = self.balls
        return o
    def pitchball(self):
        self.balls += 1
        if self.balls == 4:
            self.walk  = True
    def pitchstrike(self):
        self.strikes += 1
        if self.strikes == 3:
            self.out = True
    def pitchfoul(self):
        if self.strikes < 2:
            self.strikes += 1
    def pitchcontact(self):
        self.contact = True

    def neighbors(self):
        if self.out or self.contact or self.walk:
            return
        yield self.copy().pitchball()
        yield self.copy().pitchstrike()
        yield self.copy().pitchcontact()
        yield self.copy().pitchfoul()
        return

    def next(self):
        pitches = [ self.pitchball, self.pitchstrike, \
            self.pitchcontact, self.pitchfoul ]
        pitchDistro = RandVariable([2.,2.,1.,2.])
        pitches[pitchDistro.rand()]()
        print "\t\t"+str(self)

    def atbat(self):
        while not (self.out or self.contact or self.walk):
            self.next()


class Field:
    def __init__(self):
        self.bases = [0,0,0,0]
        self.runs = 0
        self.outs = 0
        self.verbose = True

    def __str__(self):
        s = "Runs:%d, Outs:%d, On base:"%(self.runs, self.outs)
        s = s+str(self.bases)
        return s

    def next(self):
        assert self.outs < 4
        batter = Batter()
        batter.atbat()
        if batter.out:
            self.outs += 1
        elif batter.walk:
            i = 1
            while True:
                if self.bases[i] == 0:
                    self.bases[i] = 1
                    break
                elif i == 3:
                    self.runs += 1
                    break
                i+= 1
        elif batter.contact:
            hitDistro = RandVariable([2.,2.,2.,1.,2.])
            h = hitDistro.rand()
            # use 0 to represent getting out
            if h == 0:
                self.outs += 1
            else:
                self.bases[0] = 1
                while h > 0:
                    if self.bases[3] > 0:
                        self.runs += 1
                    self.bases = [0] + self.bases[0:3]
                    h -= 1
        else:
            assert False, "should never be reached"
        print '\t'+str(self)

    def halfinning(self):
        while self.outs < 3:
            self.next()

def main():
    runs = [ 0, 0]
    print "Start of game, no score"
    for inning in range(1,10):
        for team in [0,1]:
            print "\tTeam taking the field"
            x = Field()
            x.halfinning()
            runs[team] += x.runs
            s = "\nInning: %d, Batting Team: %d"%(inning,team)
            s += "\nScore: %d to %d"%(runs[0],runs[1])
            print s
    return

if __name__ == '__main__':
    main()

An example of a simulated game

1,0,   0,0
    Team taking the field
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (2, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        Contact
    runs:0,Outs:1,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (0, 2)
        (1, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (0, 2)
        Contact
    runs:1,Outs:2,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        Contact
    runs:2,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (0, 2)
        (1, 2)
        Contact
    runs:3,Outs:2,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        Strike-out
    runs:3,Outs:3,bases:[0, 0, 0, 1]

Inning: 1, Batting Team: 0, Score: 3 to 0
    Team taking the field
        New batter
        (1, 0)
        (2, 0)
        (2, 1)
        (3, 1)
        Walk
    runs:0,Outs:0,bases:[0, 1, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (1, 2)
        (2, 2)
        (3, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (1, 2)
        (2, 2)
        (3, 2)
        Strike-out
    runs:0,Outs:3,bases:[0, 1, 0, 0]

Inning: 1, Batting Team: 1, Score: 3 to 0
    Team taking the field
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (2, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        (2, 0)
        Contact
    runs:1,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (1, 2)
        (1, 2)
        (2, 2)
        Strike-out
    runs:1,Outs:3,bases:[0, 0, 0, 0]

Inning: 2, Batting Team: 0, Score: 4 to 0
    Team taking the field
        New batter
        (0, 1)
        (0, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (2, 2)
        (3, 2)
        Walk
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        Contact
    runs:0,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        Contact
    runs:0,Outs:2,bases:[0, 0, 1, 1]
        New batter
        (1, 0)
        (2, 0)
        (3, 0)
        (3, 1)
        (3, 2)
        (3, 2)
        Strike-out
    runs:0,Outs:3,bases:[0, 0, 1, 1]

Inning: 2, Batting Team: 1, Score: 4 to 0
    Team taking the field
        New batter
        (1, 0)
        (2, 0)
        (3, 0)
        (3, 1)
        Contact
    runs:0,Outs:0,bases:[0, 1, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        Contact
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (2, 1)
        (2, 2)
        (2, 2)
        (3, 2)
        Contact
    runs:0,Outs:1,bases:[0, 0, 1, 1]
        New batter
        (0, 1)
        (0, 2)
        (1, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 0, 1, 1]
        New batter
        (0, 1)
        Contact
    runs:0,Outs:3,bases:[0, 0, 1, 1]

Inning: 3, Batting Team: 0, Score: 4 to 0
    Team taking the field
        New batter
        (0, 1)
        Contact
    runs:0,Outs:0,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (0, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (1, 1)
        (2, 1)
        (2, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 0, 0, 1]
        New batter
        Contact
    runs:1,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (1, 2)
        Contact
    runs:1,Outs:2,bases:[0, 1, 1, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        Contact
    runs:1,Outs:2,bases:[0, 1, 1, 1]
        New batter
        (0, 1)
        (0, 2)
        (1, 2)
        Strike-out
    runs:1,Outs:3,bases:[0, 1, 1, 1]

Inning: 3, Batting Team: 1, Score: 4 to 1
    Team taking the field
        New batter
        Contact
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        Contact
    runs:0,Outs:1,bases:[0, 0, 1, 0]
        New batter
        (0, 1)
        Contact
    runs:1,Outs:1,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (1, 1)
        Contact
    runs:2,Outs:1,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        Strike-out
    runs:2,Outs:2,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (0, 2)
        (1, 2)
        (2, 2)
        Contact
    runs:3,Outs:2,bases:[0, 0, 1, 0]
        New batter
        (0, 1)
        (0, 2)
        Contact
    runs:4,Outs:2,bases:[0, 0, 1, 0]
        New batter
        Contact
    runs:4,Outs:3,bases:[0, 0, 1, 0]

Inning: 4, Batting Team: 0, Score: 8 to 1
    Team taking the field
        New batter
        (0, 1)
        (0, 2)
        (1, 2)
        (1, 2)
        (2, 2)
        (3, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        Contact
    runs:1,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        Contact
    runs:1,Outs:1,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        Contact
    runs:1,Outs:2,bases:[0, 0, 0, 1]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (0, 2)
        (0, 2)
        (1, 2)
        (2, 2)
        (2, 2)
        (2, 2)
        Contact
    runs:1,Outs:3,bases:[0, 0, 0, 1]

Inning: 4, Batting Team: 1, Score: 8 to 2
    Team taking the field
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (0, 2)
        (1, 2)
        (1, 2)
        (1, 2)
        (1, 2)
        (2, 2)
        (3, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        Contact
    runs:1,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (2, 1)
        (2, 2)
        (3, 2)
        Walk
    runs:1,Outs:1,bases:[0, 1, 0, 0]
        New batter
        Contact
    runs:1,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        Contact
    runs:1,Outs:2,bases:[0, 1, 1, 0]
        New batter
        (0, 1)
        (1, 1)
        Contact
    runs:1,Outs:2,bases:[0, 1, 1, 1]
        New batter
        Contact
    runs:3,Outs:2,bases:[0, 0, 1, 1]
        New batter
        Contact
    runs:3,Outs:3,bases:[0, 0, 1, 1]

Inning: 5, Batting Team: 0, Score: 11 to 2
    Team taking the field
        New batter
        (0, 1)
        Contact
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        Contact
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (1, 0)
        Contact
    runs:0,Outs:1,bases:[0, 0, 1, 1]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (1, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 0, 1, 1]
        New batter
        (0, 1)
        (0, 2)
        Strike-out
    runs:0,Outs:3,bases:[0, 0, 1, 1]

Inning: 5, Batting Team: 1, Score: 11 to 2
    Team taking the field
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (2, 2)
        (3, 2)
        Contact
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        Contact
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        Contact
    runs:0,Outs:2,bases:[0, 1, 0, 0]
        New batter
        Contact
    runs:2,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (0, 2)
        Strike-out
    runs:2,Outs:3,bases:[0, 0, 0, 0]

Inning: 6, Batting Team: 0, Score: 13 to 2
    Team taking the field
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (1, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        Contact
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (2, 2)
        (2, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 1, 0, 0]
        New batter
        Contact
    runs:0,Outs:2,bases:[0, 0, 1, 1]
        New batter
        Contact
    runs:0,Outs:3,bases:[0, 0, 1, 1]

Inning: 6, Batting Team: 1, Score: 13 to 2
    Team taking the field
        New batter
        (0, 1)
        (1, 1)
        (2, 1)
        Contact
    runs:1,Outs:0,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        (1, 2)
        Contact
    runs:1,Outs:0,bases:[0, 0, 1, 0]
        New batter
        Contact
    runs:2,Outs:0,bases:[0, 0, 1, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (2, 2)
        (3, 2)
        Walk
    runs:2,Outs:0,bases:[0, 1, 1, 0]
        New batter
        (1, 0)
        (1, 1)
        Contact
    runs:3,Outs:0,bases:[0, 0, 1, 1]
        New batter
        Contact
    runs:4,Outs:0,bases:[0, 1, 0, 1]
        New batter
        (0, 1)
        (0, 2)
        Contact
    runs:7,Outs:0,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (1, 2)
        (2, 2)
        Strike-out
    runs:7,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        Contact
    runs:7,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (0, 2)
        (0, 2)
        Strike-out
    runs:7,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (2, 1)
        (2, 2)
        Strike-out
    runs:7,Outs:3,bases:[0, 1, 0, 0]

Inning: 7, Batting Team: 0, Score: 20 to 2
    Team taking the field
        New batter
        (1, 0)
        (2, 0)
        (3, 0)
        Walk
    runs:0,Outs:0,bases:[0, 1, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        Contact
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        Contact
    runs:0,Outs:1,bases:[0, 0, 1, 1]
        New batter
        (0, 1)
        (1, 1)
        (2, 1)
        (2, 2)
        Contact
    runs:3,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (1, 2)
        (2, 2)
        (3, 2)
        Contact
    runs:3,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (2, 2)
        (2, 2)
        Contact
    runs:3,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        (0, 2)
        (0, 2)
        Strike-out
    runs:3,Outs:3,bases:[0, 1, 0, 0]

Inning: 7, Batting Team: 1, Score: 20 to 5
    Team taking the field
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (2, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (2, 2)
        (2, 2)
        (3, 2)
        Contact
    runs:0,Outs:1,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (1, 2)
        (1, 2)
        Contact
    runs:0,Outs:1,bases:[0, 1, 1, 0]
        New batter
        (0, 1)
        (0, 2)
        (1, 2)
        (2, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 1, 1, 0]
        New batter
        (1, 0)
        (2, 0)
        (2, 1)
        (2, 2)
        (2, 2)
        Strike-out
    runs:0,Outs:3,bases:[0, 1, 1, 0]

Inning: 8, Batting Team: 0, Score: 20 to 5
    Team taking the field
        New batter
        (0, 1)
        (0, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (2, 2)
        (2, 2)
        (3, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (0, 2)
        Strike-out
    runs:0,Outs:3,bases:[0, 0, 0, 0]

Inning: 8, Batting Team: 1, Score: 20 to 5
    Team taking the field
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        (2, 1)
        (2, 2)
        Strike-out
    runs:0,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        (1, 2)
        (2, 2)
        Strike-out
    runs:0,Outs:3,bases:[0, 0, 0, 0]

Inning: 9, Batting Team: 0, Score: 20 to 5
    Team taking the field
        New batter
        Contact
    runs:0,Outs:0,bases:[0, 0, 1, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        Strike-out
    runs:0,Outs:1,bases:[0, 0, 1, 0]
        New batter
        (0, 1)
        Contact
    runs:0,Outs:1,bases:[0, 1, 0, 1]
        New batter
        (1, 0)
        (1, 1)
        Contact
    runs:3,Outs:1,bases:[0, 0, 0, 0]
        New batter
        (0, 1)
        (1, 1)
        (1, 2)
        Strike-out
    runs:3,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        Contact
    runs:4,Outs:2,bases:[0, 0, 0, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (1, 2)
        (1, 2)
        (1, 2)
        (2, 2)
        (3, 2)
        Walk
    runs:4,Outs:2,bases:[0, 1, 0, 0]
        New batter
        (0, 1)
        Contact
    runs:4,Outs:2,bases:[0, 1, 1, 0]
        New batter
        (1, 0)
        (1, 1)
        (1, 2)
        (1, 2)
        Strike-out
    runs:4,Outs:3,bases:[0, 1, 1, 0]

Inning: 9, Batting Team: 1, Score: 20 to 9