Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Little league Sabermetrics: baseball_simulation

Trying to figure out the best lineup for my kid's little league team which I coach. I'll be the first to admit they are kids and it doesn't really matter. There are unique rules like 5 runs max per inning that make normal front-loading of lineups non-optimal. I was curious on how to setup their lineup so as to maximize the total number of runs.

Terminology and Rules

Some of these terms and rules are fairly simplified, e.g. someone could hit a single and the player at first could advance two bases instead of just one. This also doesn't take into account the defense. There may be a specific defense setup. Since a lot of little leagues require you to rotate players in defensive positions, you might try to save good batters until when the best defensive player isn't pitching or playing first base. This simulation doesn't take that into account either

  • Player: This is a batter
  • 1b: Single, everyone advances one base
  • 2b: Double, everyone advances two bases
  • 3b: Triple, everyone advances three bases
  • hr: Homerun, everyone scores
  • so: Strikeout, no one advances and add one out
  • bo: Hit and thrown out, everyone advances one base except batter and add one out

Code Setup

conda env create -f requirements.yaml

There are two Notebooks in this repo and some supporting files.

The first challenge is a determining the result of a given lineup. A given lineup has a lot of possibilities. We'll limit the probabilities of the six options to where only two of them are filled in, e.g. a player has a 60% chance of single and 40% chance of strikeout. You can run through a single game and get a number or you can run a monte-carlo and get a mean or median.

What I realized is that for a given starting lineup and starting player within that lineup there are six outcomes with a max of five runs: 0-Runs, 1-Run, 2-Runs, 3-Runs, 4-Runs, or 5-Runs. So each outcome has probability. But it isn't that easy because the last one to bat also effects the start of the next inning. So really for a 10 player team with a max of 5 runs there are 60 possible outcomes. An example is you may have scored 3-Runs but the 4th batter in the lineup is up next, or you could have scored 3-Runs and the 6th batter in the lineup is up next.

How can we use this to our advantage? Instead of doing a Montecarlo simulation we can do the full permutation, or multi-hypothesis tree for each starting batter in a given lineup. Then instead of having to do monte-carlo, we can compute the tree for the each batter and get the probabilities for the 60 outcomes. Then we can treat this as a Markov chain and use linear algebra to cascade the possibilities. I'm sure there is a method like Singular-Value-Decomposition (SVD) that would solve this but I wanted to use some Genetic algorithms so...

Option 1: Genetic Algorithm with Ordered Cross-Over (deap.ipynb)

The lineup can be thought of as a set and this set can be fed through a baseball simulation or the Markov chain to determine median or mean number of runs. The ordered cross-over preserves the set so you don't have batter batting twice. See https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm).

About

Trying to figure out the best lineup for my kid's little league team

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages