UNPKG

cacatoo

Version:

Building, exploring, and sharing spatially structured models

189 lines (160 loc) 8.39 kB
<!-- Cooperation example for students DO NOT CHANGE THE FIRST 5 LINES OF CODE BELOW, THEY ARE NECESSARY FOR THE PAGE TO WORK --> <html> <script src="../../dist/cacatoo.js"></script> <!-- Include cacatoo library (compiled with rollup) --> <script src="../../lib/all.js"></script> <!-- Load other packages --> <link rel="stylesheet" href="../../style/cacatoo.css"> <!-- Set style sheet --> <!-- CODE FOR SIMULATION BEGINS HERE --> <script> // First, we define a few 'variables', which we can use to ajust the model later var sim; // This 'global' variable will hold the entire simulation var initial_helping_rate = 0.5 // Determines how much help a 'cooperative' individual gives to its neighbours var death = 0.1 // Determines how often an individual spontaneously dies, making a new spot available var movement = 1 // Determines how much individuals 'move around' var mutation_rate = 0.01 /** * function cacatoo() contains all the user-defined parts of a cacatoo-model. Configuration, update rules, what is displayed or plotted, etc. It's all here. */ function cacatoo() { /* 1. SETUP. First, set up a configuration-object. Here we define how large the grid is, how long will it run, what colours will the critters be, etc. */ let config = { // Configuration of your model. How large is the grid, how long will it run, what colours will the critters be, etc. title: "Cooperating with your neighbours (evolving)", description: "", maxtime: 1000000, ncol: 100, nrow: 100, // dimensions of the grid to build seed: 56, wrap: [false, false], // Wrap boundary [COLS, ROWS] scale: 3, // scale of the grid (nxn pixels per grid point) graph_interval: 50, show_gridname: false, graph_update: 50, statecolours: { 'alive': { 1: 'black' }} } /* 1. SETUP. (continued) Now, let's use that configuration-object to generate a new Cacatoo simulation */ sim = new Simulation(config) // Initialise a new Simulation instance with configuration given above sim.makeGridmodel("coop") // Make a new gridmodel named cheater sim.initialise = function() { let init_individuals = [{alive:1, helping_rate: initial_helping_rate, time_birth:-1}] sim.populateSpot(sim.coop, init_individuals, [1.0], 10, config.ncol/2, config.nrow/2) // Place the three 'species' in grid points (33% A, 33% B, 33% C) sim.display() } sim.createDisplay_continuous({model:"coop", property:"helping_rate", label:"Cooperation", minval: 0.0, maxval:1.0,num_colours:50, na_colour: 'black', fill:"inferno", decimals:1, nticks:3}) sim.spaceTimePlot("coop", "Cooperation", "Space-time diagram", sim.ncol/2, sim.ncol*2) /** * Define your next-state function here: for each grid point, what determines what that grid point will be like next timestep? */ sim.coop.nextState = function (x, y) // Define the next-state function. This example is two mutualists and a cheater { // let pA, pB, pC, psum let me = this.grid[x][y] if (!me.alive) // If there is no living cell here { let neighbours = this.getMoore8(this, x, y,'alive',1) let winner = this.rouletteWheel(neighbours, 'fitness', 5.0) if (winner != undefined) { me.alive = winner.alive me.parent = winner // Always know who your parent is. me.time_birth = sim.time me.helping_rate = winner.helping_rate if(this.rng.random() < mutation_rate){ let step = (2.0*this.rng.genrand_real1()-1.0)*0.3 me.helping_rate += step } if(me.helping_rate > 1.0) me.helping_rate = 1.0 if(me.helping_rate < 0.0) me.helping_rate = 0.0 } } if (this.rng.random() < death){ // Stochastic death (species become 0, which is an empty space for the next step to compete over) this.grid[x][y].alive = 0 this.grid[x][y].helping_rate = undefined this.grid[x][y].fitness = 0 } } calculatefitness = function(x,y) { sim.coop.grid[x][y].fitness = sim.coop.sumMoore8(sim.coop, x, y, "helping_rate")-0.1*sim.coop.grid[x][y].helping_rate } /** * Define your update-function here: stuff that is applied to the entire grid every timestep. E.g. apply the next-state, diffuse stuff, mix individuals, show graphs, etc. */ sim.coop.update = function () { this.updateGraphs() this.apply_sync(calculatefitness) this.asynchronous() // Update all grid points based on the next-state function (defined above) for(let i=0; i<movement;i++)this.MargolusDiffusion() // Every so often mix individuals a bit // OPTIONAL: add some graphs (see function below) } /** * OPTIONAL: add some graphs to show how your model progresses. Cacatoo currently supports three graph types, all of which are illustrated in this example */ sim.coop.updateGraphs = function () { // Let's count some stuff every update let helping_rates = [] for(let n = 0; n < 20; n++){ let x = this.rng.genrand_int(0,this.nc-1) let y = this.rng.genrand_int(0,this.nr-1) if (this.grid[x][y].alive == 1) { help = this.grid[x][y].helping_rate helping_rates.push(help) } else helping_rates.push(undefined) } // Update the plots. If the plot do not yet exist, a new plot will be automatically added by cacatoo this.plotPopsizes('alive',[1]) this.plotPoints(helping_rates,"Cooperation rates (points + average)") } sim.coop.bottleneck = function() { console.log(sim) for (let x = 0; x < this.nc; x++) { for (let y = 0; y < this.nr; y++) { if(this.rng.genrand_real1() < 0.99){ this.grid[x][y].alive = 0 this.grid[x][y].helping_rate = 0 } } } } /** * OPTIONAL: add some buttons and sliders so you can play with your model easily */ sim.addButton("Play / Pause", function () { sim.toggle_play() }) // Add a button that calls function "display" in "model" sim.addButton("Well mix", function () { sim.toggle_mix() }) // Add a button that calls function "perfectMix" in "model.cheater" sim.addButton("Catastrophe!", function () {sim.coop.bottleneck() }) sim.addButton("Restart", function () {sim.initialise() }) sim.addHTML("form_holder","<br>") sim.addSlider("mutation_rate", 0.00, 1.00, 0.001, "Mutation rate") sim.addSlider("death", 0.005, 1.00, 0.001, "Death rate") sim.addSlider("movement", 0,300,1, "Movement rate") sim.initialise() sim.start() } </script> <!-- CODE FOR SIMULATION ENDS HERE, DO NOT CHANGE BEYOND THIS POINT --> <body onload="cacatoo()"> <div class="header" id="header"> <h2>Cacatoo </h2> </div> <div class="content"> </div> <div class="content" id="canvas_holder"></div> <div class="content" id="form_holder"></div> <div class="content" id="graph_holder"></div> <div class="footer" id="footer"> </div> </body> </html>