--IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII --II Segregation Model, based on (Zhang 2004) II --II II --II Pedro Ribeiro de Andrade Neto II --II Last change: 20070131 II --IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII dofile("agents.lua") --------------------------------------------------------------------------------------------------- -- ENVIRONMENT VARIABLES --------------------------------------------------------------------------------------------------- DENSITY = 1 -- players by cell PAIRS_PER_TURN = 1 -- up to this value. be careful for this value do not be greater than half -- the number of agents TURNS = 2000 -- Z > M > 0 Z = 1.0 M = 0.6 e = 2.17 beta = 10 --------------------------------------------------------------------------------------------------- -- GENERAL FUNCTIONS --------------------------------------------------------------------------------------------------- function Populate(grid) local groups = {} for i = 1, DENSITY, 1 do if math.mod(i, 2) then groups = {"B", "A"} else groups = {"A", "B"} end ForEachCell(grid, function(c) agent = {} if math.mod(c.Lin, 2) == math.mod(c.Col, 2) then agent.Group = groups[1] else agent.Group = groups[2] end AddAgent(c, agent) return true end) end end function UpdateQuantities(cell) cell.A = 0 cell.B = 0 ForEachAgent(cell, function(cell, agent) if agent.Group == "A" then cell.A = cell.A + 1 end if agent.Group == "B" then cell.B = cell.B + 1 end end) return true end function UpdateNeighbourhoodQuantities(cell) cell.NA = 0 cell.NB = 0 ForEachNeighbour(cell, 1, function(cell, neigh) cell.NA = cell.NA + neigh.A cell.NB = cell.NB + neigh.B end) return true end function UpdateU(cell) local total_players = DENSITY * 9 local total_a = cell.NA + cell.A local total_b = cell.NB + cell.B if total_a >= total_b then cell.UA = (2 * Z - M) + total_a * (M - Z) / (total_players / 2) else cell.UA = Z * total_a / total_players end if total_b >= total_a then cell.UB = (2 * Z - M) + total_b * (M - Z) / (total_players / 2) else cell.UB = Z * total_b / total_players end return true end -- get the unsatisfaction of an _agent_ at a given _cell_ function GetUnsatisfaction(agent, cell) if agent.Group == "A" then return cell.UA end if agent.Group == "B" then return cell.UB end print "ERROR: INVALID GROUP" return 1 end function Turn(grid) for i = 1, PAIRS_PER_TURN, 1 do c1 = GetRandomCell(grid) while NumberOfAgents(c1) == 0 do -- choose a non-empty cell c1 = GetRandomCell(grid) end c2 = c1 while c2 == c1 or NumberOfAgents(c2) == 0 do -- choose another cell c2 = GetRandomCell(grid) end a1 = GetRandomAgent(c1) a2 = GetRandomAgent(c2) -- probabilities of switch u1swit = GetUnsatisfaction(a1, c2) u2swit = GetUnsatisfaction(a2, c1) u1notswit = GetUnsatisfaction(a1, c1) u2notswit = GetUnsatisfaction(a2, c2) probability = ( e ^ ( beta * (u1swit + u2swit) ) ) / ( e ^ ( beta * (u1notswit + u2notswit) ) + e ^ ( beta * (u1swit + u2swit) ) ) if probability >= math.random() then MoveTo(c1, a1, c2) MoveTo(c2, a2, c1) end end end --------------------------------------------------------------------------------------------------- -- SEGREGATION METRICS --------------------------------------------------------------------------------------------------- function Dissimilaridade(grid) N = DENSITY * NumberOfCells(grid) -- populacao total Nj = DENSITY * 9 -- populacao na unidade j (contando os seus 8 vizinhos) Tm = 0.5 -- proporcao do grupo m na cidade M = 2 -- grupos populacionais I = 0.5 -- \sum Tm *(1 - Tm) Dm = 0 ForEachCell(grid, function(cell) LjA = cell.A + cell.NA LjB = cell.B + cell.NB Lj = Nj TjA = LjA / Lj TjB = LjB / Lj D = Nj * math.mod(TjA - Tm) / (2 * N * I) + Nj * math.mod(TjB - Tm) / (2 * N * I) Dm = Dm + D end) return Dm end function Exposicao(grid) end function Isolamento(grid) end --------------------------------------------------------------------------------------------------- -- RUNNING THE MODEL --------------------------------------------------------------------------------------------------- grid = CellularSpace{ dbType = "ADO", host = "localhost", database = "c:\\terrame\\mobility.mdb", user = "", password = "", layer = "cells", theme = "cells", select = {"object_id_", "Col", "Lin"} } grid:load() CreateMooreNeighbourhood(grid) -- remove the cell itself from its neighbourhood ApplyNeighbourhoodConstraint(grid, 0, function(cell, neigh) return cell ~= neigh; end) InitAgents(grid) Populate(grid) grid:synchronize() for i = 1, TURNS, 1 do ForEachCell(grid, UpdateQuantities) ForEachCell(grid, UpdateNeighbourhoodQuantities) ForEachCell(grid, UpdateU) print (i) if math.mod(i, 400) == 1 then grid:save( i, "population", {"A", "B"} ); end Turn(grid) SynchronizeAgents() end grid:save( TURNS, "population", {"A", "B"} );