+ All Categories
Home > Documents > Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)!...

Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)!...

Date post: 16-Mar-2020
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
86
Go as an Agent-Based Model simulation tool Golang UA, Kyiv, May 18 2018 Ivan Danyliuk Status.im @idanyliuk
Transcript
Page 1: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 2: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 3: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 4: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 5: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 6: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 7: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 8: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 9: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 10: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 11: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 12: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 13: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 14: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 15: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 16: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 17: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 18: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 19: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 20: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 21: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 22: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 23: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 24: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 25: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 26: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 27: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 28: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 29: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 30: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 31: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 32: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 33: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 34: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 35: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 36: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 37: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 38: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 39: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 40: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 41: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 42: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 43: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 44: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 45: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 46: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 47: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 48: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 49: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 50: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 51: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 52: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 53: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 54: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 55: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 56: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 57: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 58: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 59: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 60: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 61: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 62: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 63: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 64: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 65: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 66: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 67: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 68: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 69: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 70: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 71: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 72: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 73: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 74: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 75: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 76: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 77: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 78: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 79: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 80: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 81: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 82: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 83: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 84: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 85: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

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

Page 86: Golang UA, Kyiv, May 18 2018 Go as an Agent-Based Model ... · Agent Based Modelling (ABM)! Technique to explore complex phenomenas! Define behavior rules for agentsRun them concurrently

Thank youidanyliuk


Recommended