Go as an Agent-Based Modelsimulation tool
Golang UA Kyiv May 18 2018
Ivan Danyliuk
Statusim
idanyliuk
What is ABM
Agent Based Modelling (ABM)
Technique to explore complex phenomenas
Define behavior rules for agents Run them concurrently many times
Observe emerging dynamics on macro-level
Agent Based Modelling (ABM)
Used in economics social sciences urban planning biomedicine etc
Examplesbull flock of birdsbull fish schoolbull humans crowdbull immune responses
Agent Based Modelling (ABM)
Opposite to equation based modelling Examples LotkandashVolterra equations ndash
predator-prey system Agent-based model reproduce the
same oscillation pattern
History of ABM
Cellular Automata by Stanislaw Ulam and John von Neumann (1940s)
Game of Life by John Horton Conway (1970s) Distributed Prisonerrsquos Dilemma by Robert
Axelrod (1980s) 1990-2000 Expansion of ABM software
Examples
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
What is ABM
Agent Based Modelling (ABM)
Technique to explore complex phenomenas
Define behavior rules for agents Run them concurrently many times
Observe emerging dynamics on macro-level
Agent Based Modelling (ABM)
Used in economics social sciences urban planning biomedicine etc
Examplesbull flock of birdsbull fish schoolbull humans crowdbull immune responses
Agent Based Modelling (ABM)
Opposite to equation based modelling Examples LotkandashVolterra equations ndash
predator-prey system Agent-based model reproduce the
same oscillation pattern
History of ABM
Cellular Automata by Stanislaw Ulam and John von Neumann (1940s)
Game of Life by John Horton Conway (1970s) Distributed Prisonerrsquos Dilemma by Robert
Axelrod (1980s) 1990-2000 Expansion of ABM software
Examples
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Agent Based Modelling (ABM)
Technique to explore complex phenomenas
Define behavior rules for agents Run them concurrently many times
Observe emerging dynamics on macro-level
Agent Based Modelling (ABM)
Used in economics social sciences urban planning biomedicine etc
Examplesbull flock of birdsbull fish schoolbull humans crowdbull immune responses
Agent Based Modelling (ABM)
Opposite to equation based modelling Examples LotkandashVolterra equations ndash
predator-prey system Agent-based model reproduce the
same oscillation pattern
History of ABM
Cellular Automata by Stanislaw Ulam and John von Neumann (1940s)
Game of Life by John Horton Conway (1970s) Distributed Prisonerrsquos Dilemma by Robert
Axelrod (1980s) 1990-2000 Expansion of ABM software
Examples
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Agent Based Modelling (ABM)
Used in economics social sciences urban planning biomedicine etc
Examplesbull flock of birdsbull fish schoolbull humans crowdbull immune responses
Agent Based Modelling (ABM)
Opposite to equation based modelling Examples LotkandashVolterra equations ndash
predator-prey system Agent-based model reproduce the
same oscillation pattern
History of ABM
Cellular Automata by Stanislaw Ulam and John von Neumann (1940s)
Game of Life by John Horton Conway (1970s) Distributed Prisonerrsquos Dilemma by Robert
Axelrod (1980s) 1990-2000 Expansion of ABM software
Examples
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Agent Based Modelling (ABM)
Opposite to equation based modelling Examples LotkandashVolterra equations ndash
predator-prey system Agent-based model reproduce the
same oscillation pattern
History of ABM
Cellular Automata by Stanislaw Ulam and John von Neumann (1940s)
Game of Life by John Horton Conway (1970s) Distributed Prisonerrsquos Dilemma by Robert
Axelrod (1980s) 1990-2000 Expansion of ABM software
Examples
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
History of ABM
Cellular Automata by Stanislaw Ulam and John von Neumann (1940s)
Game of Life by John Horton Conway (1970s) Distributed Prisonerrsquos Dilemma by Robert
Axelrod (1980s) 1990-2000 Expansion of ABM software
Examples
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Examples
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Game of Life (Conway 1970)
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Crowd simulation
Source httpswwwyoutubecomwatchv=hpYdjHzHTkY
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Facilities evacuation simulations
Source httpswwwyoutubecomwatchv=bTp1DRfULII
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Traffic simulations
Source httpswwwyoutubecomwatchv=h3HLzMJ-ac8
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
Most of the ABM software isbull Hard to usebull Complexbull Uglybull Slowbull Java
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Mason
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
NetLogo
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GAMA
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
AnyLogic
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
RePast
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software Issues
New programming language
UI Interface
Performance scalability
Installation issues
Hardto use
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Good luck trying to play with even simple model on your weekend
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
What exactly ABM software does
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
Program model in high-level simple language
Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
Program model in high-level simple language Run many models concurrently
Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
ABM Software
Program model in high-level simple language Run many models concurrently Compute interactionsworldstate
Collectanalyze worldmodel
Present result via some UI
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Gopher
Sounds like a plan
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABMgithubcomdivangoabm
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Whats important for ABM framework
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Whats important for ABM framework
Engine
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Whats important for ABM framework
Engine
Model
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Whats important for ABM framework
Engine
ModelWorld
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Whats important for ABM framework
Engine
UI
World Model
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Whats important for ABM framework
Engine
UI
World Model
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Engine
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABM
ABM is an engine of the simulation framework It connects the Agents Worlds and UI and runs the actual simulation type ABM struct private fields
func (ABM) AddAgent(a Agent)
func (ABM) StartSimulation()
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABM
for i = 0 i lt aLimit() i++ if aWorld() = nil aWorld()Tick() var wg syncWaitGroup for j = 0 j lt aAgentsCount() j++ wgAdd(1) go func(wg syncWaitGroup j int) aagents[j]Run() wgDone() (ampwg j) wgWait() if areportFunc = nil areportFunc(a)
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Agent
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
GoABM
Agent defines a model of independent agents behavior type Agent interface Run()
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Human implements Agent for human that can age type Human struct age int dead bool zero values must be useful )
func (h Human) Run() If hdead return hage++ if hage == AvgDeathAge hDie()
func (h Human) Die() hdead = true
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Agent model
You can create any type of actions
Use random generators for different probability
distributions
bull githubcomatgjackprob
bull httpwwwgonumorg
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
World
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
World
World is where agent interact and have locationbull Continiousbull Discrete (grids)bull Graphsbull GIS data (geography)
Non-spatial worldsbull Belief spacebull XOR-distance based P2P networks
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
World represents space in which agents dwell and interact It updates the state on each Tick() type World interface Tick() mark the beginning of the next time period
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI defines the minimal user interface type type UI interface Stop() Loop()
type Charts interface AddChart(name string values lt-chan float64)
type Grid interface AddGrid(lt-chan [][]interface)
type Grid3D interface AddGrid3D(lt-chan []interface)
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI
Console terminal
Native Desktop (xexpshiny)
Web-based WebGL
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
User code
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
func main() a = abmNew() aSetWorld(gridNew(100 100)) aAddAgent(ampHuman)
ch = make(chan int) aSetReportFunc(func(a abmABM) ch lt- aCount(func(agent abmAgent) bool return agent(humanHuman)IsAlive() ) ) go aStartSimulation()
ui = termNewUI() defer uiStop() uiAddChart(Humans Alive ch) uiLoop()
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Demo time
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(200)
alivesCh = make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiLoop()
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI implementing uiCharts interface
package main
import ( githubcomdivangoabmabm githubcomdivangoabmmodelshuman githubcomdivangoabmuiterm )
func main() a = abmNew()
for i = 0 i lt 100 i++ aAddAgent(humanNew(a))
aLimitIterations(500)
alivesCh newbornsCh = make(chan float64) make(chan float64) aSetReportFunc(func(a abmABM) alive = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hIsAlive() ) alivesCh lt- float64(alive)
newborns = aCount(func(agent abmAgent) bool h = agent(humanHuman) return hAge() lt 3 ) newbornsCh lt- float64(newborns) )
go aStartSimulation()
ui = termNewUI() defer uiStop()
uiAddChart(Humans Alive alivesCh) uiAddChart(Newborns newbornsCh)
uiLoop()
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
UI implementing uiCharts interface
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Game of Life example
Run runs single iteration over cell Any live cell with fewer than two live neighbors dies as if caused by under population Any live cell with two or three live neighbors lives on to the next generation Any live cell with more than three live neighbors dies as if by overpopulation Any dead cell with exactly three live neighbors becomes a live cell as if by reproduction func (c Cell) Run() neighbors = cCountNeighbors() if cIsAlive() if neighbors lt 2 || neighbors gt 3 cDie() else if neighbors == 3 cReborn()
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Game of Life example
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Game of Life example
package main
import ( mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsconway_life githubcomdivangoabmuishiny_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 g = gridNew(w h) aSetWorld(g)
populate grid randomly for x = 0 x lt w x++ for y = 0 y lt h y++ alive = randFloat64() gt 05
cell = lifeNew(a x y alive) aAddAgent(cell) gSetCell(x y cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- gDump(lifeIsAlive) timeSleep(10 timeMillisecond) )
go aStartSimulation()
ui = shinyNew() defer uiStop() uiAddGrid(ch) uiLoop()
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Game of Life example
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
func (w Walker) Run() rx = randIntn(4) oldx oldy = wx wy switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy--
var err error if wtrail err = wgridCopy(oldx oldy wx wy) else err = wgridMove(oldx oldy wx wy)
if err = nil wx wy = oldx oldy
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = termgridTermSize() grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = termgridNew() defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
package main
import ( log mathrand time
githubcomdivangoabmabm githubcomdivangoabmmodelsrandom_walker githubcomdivangoabmuiterm_grid githubcomdivangoabmworldsgrid2d )
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h = 300 200 grid2D = gridNew(w h) aSetWorld(grid2D)
cell err = walkerNew(a randIntn(w-1) randIntn(h-1) true) if err = nil
logFatal(err) aAddAgent(cell) grid2DSetCell(cellX() cellY() cell)
ch = make(chan [][]interface) aSetReportFunc(func(a abmABM) ch lt- grid2DDump(func(a abmAgent) bool return a = nil ) )
go func() aStartSimulation() close(ch) ()
ui = shinyNew(w h) defer uiStop() uiAddGrid(ch) uiLoop()
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
func (w Walker) Run() rx = randIntn(6) oldx oldy oldz = wx wy wz switch rx case 0 wx++ case 1 wy++ case 2 wx-- case 3 wy-- case 4 wz++ case 5 wz-- err = wabmWorld()(gridGrid)Copy(oldx oldy oldz wx wy wz) if err = nil wx wy wz = oldx oldy oldz
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
func main() randSeed(timeNow()UnixNano()) a = abmNew() w h d = 100 100 100 g = gridNew(w h d) aSetWorld(g)
for i = 0 i lt 10 i++ cell = NewWalker(a randIntn(w) randIntn(h) randIntn(d)) aAddAgent(cell) gSetCell(cellx celly cellz cell)
aLimitIterations(10000)
ch = make(chan []interface) aSetReportFunc(func(a abmABM)
ch lt- gDump(func(a abmAgent) bool return a = nil ) )
go func() timeSleep(1 timeSecond) aStartSimulation() close(ch) ()
ui3d = uiNew(w h d) defer ui3dStop() ui3dAddGrid3D(ch) ui3dLoop()
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Random Walk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Bonus wrap existing Go software into Agent interface
Example simulation of Whisper P2P messaging protocol using go-ethereum codebase
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Whisper simulation
Source httpswwwyoutubecomwatchv=lt54a1ELUwE
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Conclusions
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Conclusions
A good fit for models language (simple
readable easy to learn) Allows reusing existing software (eg
networking simulations) Testable (you can write state-of-the-art
tests for your models)
ModelLanguage
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Conclusions
Nothing on CPU can beat GPU-optimized simulations
Currently not optimized at all and gives decent performance on classic models
Huge space for further optimization Good flexibility in what can be optimized on
framework side vs user model side
Performance
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Conclusions
No out of the box high-level UI solutions But many options available (console native
desktop Canvas WebGL based) Framework can provide UIs for most common
cases Truly awesome flexibility with UIs (switch between
console to WebGL with one line of code)
UI
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
goabm is pretty much work-in-progressproof-of-concept pet project
may be a good fit to develop models before running large-scale simulation
will be open sourced soon
Thank youidanyliuk
Thank youidanyliuk