Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2015 Romain Reuillon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.iscpif.spacematters.model.container

import fr.iscpif.spacematters.model.Cell

import scala.util.Random

trait Container {

def size : Int

def container(implicit rng: Random): Seq[Seq[Cell]]



/**
* Stringify just to check validity of generators ; has no sense in general context as a new instance will be randomly generated at each
* call of container.
*
* @return
*/
override def toString: String = {
var res = ""
container(new Random).foreach(
(row : Seq[Cell]) => {
row.foreach(
(c : Cell) => {res = res +c.capacity+" | "}
)
res = res + "\n"
}
)
res
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package fr.iscpif.spacematters.model.container

import fr.iscpif.spacematters.model.Cell

import scala.util.Random

trait ExpMixtureContainer <: Container {

/** maximal capacity C_m */
def maxCapacity : Int

/** Size of exponential kernels, of the form C_m*exp(-||x-x_0||/r_0) */
def kernelRadius : Double

/** Number of exponential kernels */
def centersNumber : Int

def container(implicit rng: Random) = {
val arrayVals = Array.fill[Cell](size, size) {
new Cell(0, 0, 0)
}

// generate random center positions
val centers = Array.fill[Int](centersNumber, 2) {
rng.nextInt(size)
}

for (i <- 0 to size - 1; j <- 0 to size - 1) {
for (c <- 0 to centersNumber - 1) {
arrayVals(i)(j).capacity = arrayVals(i)(j).capacity + maxCapacity * math.exp(-math.sqrt(math.pow((i - centers(c)(0)), 2) + math.pow((j - centers(c)(1)), 2)) / kernelRadius)
}
}

Seq.tabulate(size,size){(i:Int,j:Int)=>Cell(arrayVals(i)(j).capacity,0,0) }

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package fr.iscpif.spacematters.model.container

import fr.iscpif.spacematters.model.Cell

import scala.util.Random

trait PrefAttDiffusionContainer <: Container {

/** sum of all capacities */
def totalCapacity : Double

/** diffusion parameters */
def diffusion : Double
def diffusionSteps : Int

/** Growth rate */
def growthRate : Int

/** Preferential attachment parameter */
def alphaAtt : Double




/**
*
* @param rng
* @return
*/
def container(implicit rng: Random) = {
var arrayVals = Array.fill[Cell](size, size){new Cell(0,0,0)}
var population :Double = 0

while(population < totalCapacity) {

// add new population following pref att rule
if(population==0){
//choose random patch
for(_<- 1 to growthRate){val i = rng.nextInt(size);val j = rng.nextInt(size) ; arrayVals(i)(j).capacity = arrayVals(i)(j).capacity + 1 }
} else{
val oldPop = arrayVals.clone()
val ptot = oldPop.flatten.map((c:Cell)=>math.pow(c.capacity / population , alphaAtt)).sum

/*
val drawings = Array.fill[Double](growthRate){rng.nextDouble()}
Sorting.quickSort(drawings)
var s = 0.0; var i =0;var j =0;var k=0;
oldPop.flatten.foreach(
(c:Cell)=>{
s=s+(math.pow(c.capacity/population,alphaAtt)/ptot)
while(s<drawings(k)){arrayVals(i)(j).capacity = arrayVals(i)(j).capacity + 1;k=k+1;}
j=j+1;if(j==size){j=0;i=i+1};
}
)
*/

for(_<- 1 to growthRate){
var s = 0.0 ; val r = rng.nextDouble() ; var i =0;var j =0
while(s<r){s=s+(math.pow(oldPop(i)(j).capacity/population,alphaAtt)/ptot);j=j+1;if(j==size){j=0;i=i+1}}
if(j==0){j=size-1;i = i - 1}else{j=j-1};
arrayVals(i)(j).capacity = arrayVals(i)(j).capacity + 1
}
}

// diffuse
for (_ <- 1 to diffusionSteps) {
arrayVals = diffuse(arrayVals, diffusion)
}

// update total population
population = arrayVals.flatten.map(_.capacity).sum

//println("population : "+population)
}

Seq.tabulate(size,size){(i:Int,j:Int)=>Cell(arrayVals(i)(j).capacity,0,0) }


}






/**
* Diffuse to neighbors proportion alpha of capacities
* @param a
*/
def diffuse(a : Array[Array[Cell]],alpha : Double): Array[Array[Cell]] = {
val newVals = a.clone()
for (i <- 0 to size - 1; j <- 0 to size - 1) {
if(i>=1){newVals(i-1)(j).capacity = newVals(i-1)(j).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
if(i<size-1){newVals(i+1)(j).capacity = newVals(i+1)(j).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
if(j>=1){newVals(i)(j-1).capacity = newVals(i)(j-1).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
if(j<size-1){newVals(i)(j+1).capacity = newVals(i)(j+1).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
if(i>=1&&j>=1){newVals(i-1)(j-1).capacity = newVals(i-1)(j-1).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
if(i>=1&&j<size-1){newVals(i-1)(j+1).capacity = newVals(i-1)(j+1).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
if(i<size-1&&j>=1){newVals(i+1)(j-1).capacity = newVals(i+1)(j-1).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
if(i<size-1&&j<size-1){newVals(i+1)(j+1).capacity = newVals(i+1)(j+1).capacity + (alpha / 8)*a(i)(j).capacity ; newVals(i)(j).capacity = newVals(i)(j).capacity - (alpha / 8)*a(i)(j).capacity }
}
newVals
}





}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fr.iscpif.spacematters.model.container

import fr.iscpif.spacematters.model.Cell

import scala.util.Random


trait RandomContainer <: Container {

def maxCapacity : Int

def container(implicit rng: Random) = {
Seq.fill(size, size) {
val capacity: Double = rng.nextInt(maxCapacity).toDouble
Cell(capa = capacity, green = 0, red = 0)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package fr.iscpif.spacematters.model.test

import fr.iscpif.spacematters.model.container._

import scala.util.Random

object TestContainer extends App {

val t = System.currentTimeMillis()

implicit val rng = new Random

val cont = new PrefAttDiffusionContainer{
override def size: Int = 50

/*// exp Mixture params
override def kernelRadius = 0.5
override def centersNumber = 2
*/

//prefAttdiff
override def totalCapacity :Double = 10000
override def diffusion : Double = 0.02
override def diffusionSteps : Int = 2
override def growthRate : Int = 100
override def alphaAtt : Double = 1.1
}

// generate instance of container
println(cont)
// an other
println(cont)

//println((System.currentTimeMillis()-t)/1000.0)

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ object Cell {
val empty = Cell(0, 0, 0)
}

case class Cell(capacity: Int, green: Int, red: Int) {
case class Cell(capa: Double, green: Int, red: Int) {

var capacity = capa

def isFull = population >= capacity
def isEmpty = population <= 0
def population = red + green
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ package fr.iscpif.spacematters.model

import fr.iscpif.spacematters.model.initial._
import fr.iscpif.spacematters.model.move._
import fr.iscpif.spacematters.model.initial.InitialState
import fr.iscpif.spacematters.model.move.Moves

import scala.util.Random

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import initial._
import move._
import metric._
import stop._
import Moran._
import container._
import metric.Moran

import scalax.io.Resource

Expand All @@ -16,12 +17,21 @@ object Simulation extends App {

implicit val rng = new Random

val simulation = new Schelling with RandomState with RandomMoves with SpeilmanStop {
val simulation = new Schelling with RandomState with RandomContainer with RandomMoves with SpeilmanStop {
override def size: Int = 50
override def greenRatio: Double = 0.5
override def redRatio: Double = 0.35
override def maxCapacity: Int = 50
override def similarWanted: Double = 0.4

/*
override def totalCapacity :Double = 50000
override def diffusion : Double = 0.02
override def diffusionSteps : Int = 2
override def growthRate : Int = 100
override def alphaAtt : Double = 1.1
*/

}

simulation.run
Expand All @@ -40,7 +50,7 @@ object Simulation extends App {
(state, step) <- simulation.states.take(100).zipWithIndex
} {
def unsatisfied = simulation.unsatisfieds(state).map(_.number).sum
println(s"Step $step: # of unsatisfied: $unsatisfied, Dissimilarity D: ${"%.3f".format(dissimilarity(state, Green, Red))}, Moran I Red: ${"%.3f".format(colorRatioMoran(state, Red))}, Entropy H: ${"%.3f".format(segregationEntropy(state, Green, Red))}, Exposure Reds to Greens :${"%.3f".format(exposureOfColor1ToColor2(state, Red, Green))}, Isolation Reds :${"%.3f".format(isolation(state, Red, Green))}, Concentration Greens : ${"%.3f".format(delta(state, Green, Red))}")
println(s"Step $step: # of unsatisfied: $unsatisfied, Dissimilarity D: ${"%.3f".format(dissimilarity(state, Green, Red))}, Moran I Red: ${"%.3f".format(Moran.colorRatioMoran(state, Red))}, Entropy H: ${"%.3f".format(segregationEntropy(state, Green, Red))}, Exposure Reds to Greens :${"%.3f".format(exposureOfColor1ToColor2(state, Red, Green))}, Isolation Reds :${"%.3f".format(isolation(state, Red, Green))}, Concentration Greens : ${"%.3f".format(delta(state, Green, Red))}")

for { (position @ (i, j), c) <- state.cells } {
def agents = Color.all.map(_.cellColor.get(c)).mkString(",")
Expand All @@ -56,7 +66,7 @@ object Simulation extends App {
val similarWanted = simulation.similarWanted

output2.append(
s"""$step, $unsatisfied,${dissimilarity(state, Green, Red)}, ${colorRatioMoran(state, Red)}, ${segregationEntropy(state, Green, Red)}, ${exposureOfColor1ToColor2(state, Red, Green)},${exposureOfColor1ToColor2(state, Green, Red)}, ${isolation(state, Red, Green)}, ${isolation(state, Green, Red)},${delta(state, Red, Green)},${delta(state, Green, Red)}, $size, $greenRatio,$redRatio, $maxCapacity, $similarWanted\n""".stripMargin)
s"""$step, $unsatisfied,${dissimilarity(state, Green, Red)}, ${Moran.colorRatioMoran(state, Red)}, ${segregationEntropy(state, Green, Red)}, ${exposureOfColor1ToColor2(state, Red, Green)},${exposureOfColor1ToColor2(state, Green, Red)}, ${isolation(state, Red, Green)}, ${isolation(state, Green, Red)},${delta(state, Red, Green)},${delta(state, Green, Red)}, $size, $greenRatio,$redRatio, $maxCapacity, $similarWanted\n""".stripMargin)

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@
package fr.iscpif.spacematters.model.initial

import fr.iscpif.spacematters.model._
import fr.iscpif.spacematters.model.container._

import scala.util.Random

trait RandomState <: InitialState { self: Schelling =>
trait RandomState <: InitialState with Container { self: Schelling =>

def maxCapacity: Int

def initialState(implicit rng: Random) = {
val cells = Seq.fill(size, size) {
val capacity = rng.nextInt(maxCapacity)
Cell(capacity = capacity, green = 0, red = 0)
}

val cells = container(rng)

val totalCapacity = cells.flatten.map(_.capacity).sum
val greens = (totalCapacity * greenRatio).toInt
Expand Down
Loading