From fd9e6f56c03d398c38c564769006c9715f6cfd7b Mon Sep 17 00:00:00 2001 From: JusteRaimbault Date: Fri, 19 Jun 2015 11:01:29 +0200 Subject: [PATCH 1/6] branching --- .../fr/iscpif/schelling/quantity/initial/RandomState.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomState.scala b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomState.scala index 2bda645..0c66bbe 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomState.scala +++ b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomState.scala @@ -25,6 +25,8 @@ trait RandomState <: InitialState { 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) From e27434fef0ba976f5018816e072c999100fab3b2 Mon Sep 17 00:00:00 2001 From: JusteRaimbault Date: Tue, 23 Jun 2015 18:41:46 +0200 Subject: [PATCH 2/6] Containers_implementation --- .../fr/iscpif/schelling/quantity/Cell.scala | 5 +- .../schelling/quantity/Simulation.scala | 11 +- .../quantity/initial/Container.scala | 44 +++++++ .../initial/ExpMixtureContainer.scala | 48 ++++++++ .../initial/PrefAttDiffusionContainer.scala | 114 ++++++++++++++++++ .../quantity/initial/RandomContainer.scala | 22 ++++ .../quantity/initial/RandomState.scala | 7 +- .../quantity/test/TestContainer.scala | 46 +++++++ 8 files changed, 290 insertions(+), 7 deletions(-) create mode 100644 model/src/main/scala/fr/iscpif/schelling/quantity/initial/Container.scala create mode 100644 model/src/main/scala/fr/iscpif/schelling/quantity/initial/ExpMixtureContainer.scala create mode 100644 model/src/main/scala/fr/iscpif/schelling/quantity/initial/PrefAttDiffusionContainer.scala create mode 100644 model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomContainer.scala create mode 100644 model/src/main/scala/fr/iscpif/schelling/quantity/test/TestContainer.scala diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/Cell.scala b/model/src/main/scala/fr/iscpif/schelling/quantity/Cell.scala index 8dd69f9..707a4f0 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/Cell.scala +++ b/model/src/main/scala/fr/iscpif/schelling/quantity/Cell.scala @@ -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 diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/Simulation.scala b/model/src/main/scala/fr/iscpif/schelling/quantity/Simulation.scala index a0c51ba..5fd3fb3 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/Simulation.scala +++ b/model/src/main/scala/fr/iscpif/schelling/quantity/Simulation.scala @@ -15,12 +15,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 diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/Container.scala b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/Container.scala new file mode 100644 index 0000000..2386980 --- /dev/null +++ b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/Container.scala @@ -0,0 +1,44 @@ +/* + * 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 . + */ +package fr.iscpif.schelling.quantity.initial + +import fr.iscpif.schelling.quantity._ + +import scala.util.Random + +trait Container { + + def size : Int + + var values : Seq[Seq[Cell]] + + def container(implicit rng: Random): Seq[Seq[Cell]] + + def printContainer: Unit = { + values.foreach( + (row : Seq[Cell]) => { + row.foreach( + (c : Cell) => {print(c.capacity);print(" | ")} + ) + println() + } + ) + + } + + +} diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/ExpMixtureContainer.scala b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/ExpMixtureContainer.scala new file mode 100644 index 0000000..5a787e0 --- /dev/null +++ b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/ExpMixtureContainer.scala @@ -0,0 +1,48 @@ +package fr.iscpif.schelling.quantity.initial + +import fr.iscpif.schelling.quantity.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 + + var values : Seq[Seq[Cell]] = null + + 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) + //println(i + " " + j + " : " + arrayVals(i)(j).capacity) + } + } + + //println(arrayVals.toSeq) + //val a = arrayVals.map({a:Array[Cell]=>a.toSeq}) + //for(k <- 0 to a.length - 1){println(a(k))} + //println(arrayVals.map({a:Array[Cell]=>a.toSeq}).toSeq) + //values = arrayVals.map({ a: Array[Cell] => a.toSeq }).toSeq + + values = Seq.tabulate(size,size){(i:Int,j:Int)=>Cell(arrayVals(i)(j).capacity,0,0) } + + values + } + + } diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/PrefAttDiffusionContainer.scala b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/PrefAttDiffusionContainer.scala new file mode 100644 index 0000000..ba90701 --- /dev/null +++ b/model/src/main/scala/fr/iscpif/schelling/quantity/initial/PrefAttDiffusionContainer.scala @@ -0,0 +1,114 @@ +package fr.iscpif.schelling.quantity.initial + +import fr.iscpif.schelling.quantity.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 + + + + + var values : Seq[Seq[Cell]] = null + + + + + /** + * + * @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(sCell(arrayVals(i)(j).capacity,0,0) } + values + + } + + + + + + + /** + * 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=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=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=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 +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 diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/test/TestContainer.scala b/model/src/main/scala/fr/iscpif/schelling/quantity/test/TestContainer.scala new file mode 100644 index 0000000..0552f4c --- /dev/null +++ b/model/src/main/scala/fr/iscpif/schelling/quantity/test/TestContainer.scala @@ -0,0 +1,46 @@ +package fr.iscpif.schelling.quantity.test + +import fr.iscpif.schelling.quantity.Schelling +import fr.iscpif.schelling.quantity.initial._ +import fr.iscpif.schelling.quantity.move._ +import fr.iscpif.schelling.quantity.stop._ + +import scala.util.Random + +object TestContainer extends App { + + val t = System.currentTimeMillis() + + implicit val rng = new Random + + val simulation = new Schelling with RandomState with PrefAttDiffusionContainer 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 + + /*// 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 initial state + simulation.initialState(rng) + + // print container + //simulation.printContainer + + println(simulation.values.flatten.map(_.capacity).max) + + println((System.currentTimeMillis()-t)/1000.0) + +} From bc40a5c003b6c6c2e824b0ca0d1e5111749cd82d Mon Sep 17 00:00:00 2001 From: JusteRaimbault Date: Tue, 23 Jun 2015 23:32:41 +0200 Subject: [PATCH 3/6] reorganisation --- .../model/container}/Container.scala | 4 ++-- .../model/container}/ExpMixtureContainer.scala | 4 +--- .../model/container}/PrefAttDiffusionContainer.scala | 4 ++-- .../model/container}/RandomContainer.scala | 9 +++------ .../model}/test/TestContainer.scala | 11 ++++++----- 5 files changed, 14 insertions(+), 18 deletions(-) rename model/src/main/scala/fr/iscpif/{schelling/quantity/initial => spacematters/model/container}/Container.scala (92%) rename model/src/main/scala/fr/iscpif/{schelling/quantity/initial => spacematters/model/container}/ExpMixtureContainer.scala (94%) rename model/src/main/scala/fr/iscpif/{schelling/quantity/initial => spacematters/model/container}/PrefAttDiffusionContainer.scala (97%) rename model/src/main/scala/fr/iscpif/{schelling/quantity/initial => spacematters/model/container}/RandomContainer.scala (60%) rename model/src/main/scala/fr/iscpif/{schelling/quantity => spacematters/model}/test/TestContainer.scala (79%) diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/Container.scala b/model/src/main/scala/fr/iscpif/spacematters/model/container/Container.scala similarity index 92% rename from model/src/main/scala/fr/iscpif/schelling/quantity/initial/Container.scala rename to model/src/main/scala/fr/iscpif/spacematters/model/container/Container.scala index 2386980..b5e3618 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/Container.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/container/Container.scala @@ -14,9 +14,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package fr.iscpif.schelling.quantity.initial +package fr.iscpif.spacematters.model.container -import fr.iscpif.schelling.quantity._ +import fr.iscpif.spacematters.model.Cell import scala.util.Random diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/ExpMixtureContainer.scala b/model/src/main/scala/fr/iscpif/spacematters/model/container/ExpMixtureContainer.scala similarity index 94% rename from model/src/main/scala/fr/iscpif/schelling/quantity/initial/ExpMixtureContainer.scala rename to model/src/main/scala/fr/iscpif/spacematters/model/container/ExpMixtureContainer.scala index 5a787e0..ccade2d 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/ExpMixtureContainer.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/container/ExpMixtureContainer.scala @@ -1,6 +1,4 @@ -package fr.iscpif.schelling.quantity.initial - -import fr.iscpif.schelling.quantity.Cell +package fr.iscpif.spacematters.model.container import scala.util.Random diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/PrefAttDiffusionContainer.scala b/model/src/main/scala/fr/iscpif/spacematters/model/container/PrefAttDiffusionContainer.scala similarity index 97% rename from model/src/main/scala/fr/iscpif/schelling/quantity/initial/PrefAttDiffusionContainer.scala rename to model/src/main/scala/fr/iscpif/spacematters/model/container/PrefAttDiffusionContainer.scala index ba90701..a93348a 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/PrefAttDiffusionContainer.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/container/PrefAttDiffusionContainer.scala @@ -1,6 +1,6 @@ -package fr.iscpif.schelling.quantity.initial +package fr.iscpif.spacematters.model.container -import fr.iscpif.schelling.quantity.Cell +import fr.iscpif.spacematters.model.Cell import scala.util.Random diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomContainer.scala b/model/src/main/scala/fr/iscpif/spacematters/model/container/RandomContainer.scala similarity index 60% rename from model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomContainer.scala rename to model/src/main/scala/fr/iscpif/spacematters/model/container/RandomContainer.scala index 893d34c..d6a5e6e 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/initial/RandomContainer.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/container/RandomContainer.scala @@ -1,6 +1,6 @@ -package fr.iscpif.schelling.quantity.initial +package fr.iscpif.spacematters.model.container -import fr.iscpif.schelling.quantity.Cell +import fr.iscpif.spacematters.model.Cell import scala.util.Random @@ -9,14 +9,11 @@ trait RandomContainer <: Container { def maxCapacity : Int - var values : Seq[Seq[Cell]] = null - def container(implicit rng: Random) = { - values = Seq.fill(size, size) { + Seq.fill(size, size) { val capacity: Double = rng.nextInt(maxCapacity).toDouble Cell(capa = capacity, green = 0, red = 0) } - values } } diff --git a/model/src/main/scala/fr/iscpif/schelling/quantity/test/TestContainer.scala b/model/src/main/scala/fr/iscpif/spacematters/model/test/TestContainer.scala similarity index 79% rename from model/src/main/scala/fr/iscpif/schelling/quantity/test/TestContainer.scala rename to model/src/main/scala/fr/iscpif/spacematters/model/test/TestContainer.scala index 0552f4c..9231cc3 100644 --- a/model/src/main/scala/fr/iscpif/schelling/quantity/test/TestContainer.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/test/TestContainer.scala @@ -1,9 +1,10 @@ -package fr.iscpif.schelling.quantity.test +package fr.iscpif.spacematters.model.test -import fr.iscpif.schelling.quantity.Schelling -import fr.iscpif.schelling.quantity.initial._ -import fr.iscpif.schelling.quantity.move._ -import fr.iscpif.schelling.quantity.stop._ +import fr.iscpif.spacematters.model._ +import fr.iscpif.spacematters.model.container._ +import fr.iscpif.spacematters.model.initial._ +import fr.iscpif.spacematters.model.move._ +import fr.iscpif.spacematters.model.stop._ import scala.util.Random From c8ddb70c31673b38bd374b352f8d8e0380689ec9 Mon Sep 17 00:00:00 2001 From: JusteRaimbault Date: Tue, 23 Jun 2015 23:50:56 +0200 Subject: [PATCH 4/6] modifs --- .../iscpif/spacematters/model/Schelling.scala | 4 +--- .../spacematters/model/Simulation.scala | 1 + .../model/container/Container.scala | 21 +++++++++++------ .../model/container/ExpMixtureContainer.scala | 14 +++-------- .../container/PrefAttDiffusionContainer.scala | 9 ++------ .../model/initial/InitialState.scala | 1 - .../model/initial/RandomState.scala | 2 +- .../spacematters/model/move/Moves.scala | 1 - .../model/move/Neighborhood.scala | 2 +- .../model/move/Unsatisfieds.scala | 2 +- .../model/stop/SpeilmanStop.scala | 2 +- .../model/test/TestContainer.scala | 23 +++++-------------- 12 files changed, 31 insertions(+), 51 deletions(-) diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala b/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala index 07f20ec..4970fab 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala @@ -16,10 +16,8 @@ */ package fr.iscpif.spacematters.model -import fr.iscpif.schelling.quantity.initial._ -import fr.iscpif.schelling.quantity.move._ import fr.iscpif.spacematters.model.initial.InitialState -import fr.iscpif.spacematters.model.move.Moves +import fr.iscpif.spacematters.model.move._ import scala.util.Random diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala b/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala index 23f5a74..53b7f3b 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala @@ -6,6 +6,7 @@ import initial._ import move._ import metric._ import stop._ +import container._ import scalax.io.Resource diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/container/Container.scala b/model/src/main/scala/fr/iscpif/spacematters/model/container/Container.scala index b5e3618..f2334cb 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/container/Container.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/container/Container.scala @@ -24,20 +24,27 @@ trait Container { def size : Int - var values : Seq[Seq[Cell]] - def container(implicit rng: Random): Seq[Seq[Cell]] - def printContainer: Unit = { - values.foreach( + + + /** + * 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) => {print(c.capacity);print(" | ")} + (c : Cell) => {res = res +c.capacity+" | "} ) - println() + res = res + "\n" } ) - + res } diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/container/ExpMixtureContainer.scala b/model/src/main/scala/fr/iscpif/spacematters/model/container/ExpMixtureContainer.scala index ccade2d..0bb2358 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/container/ExpMixtureContainer.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/container/ExpMixtureContainer.scala @@ -1,5 +1,7 @@ package fr.iscpif.spacematters.model.container +import fr.iscpif.spacematters.model.Cell + import scala.util.Random trait ExpMixtureContainer <: Container { @@ -13,8 +15,6 @@ trait ExpMixtureContainer <: Container { /** Number of exponential kernels */ def centersNumber : Int - var values : Seq[Seq[Cell]] = null - def container(implicit rng: Random) = { val arrayVals = Array.fill[Cell](size, size) { new Cell(0, 0, 0) @@ -28,19 +28,11 @@ trait ExpMixtureContainer <: Container { 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) - //println(i + " " + j + " : " + arrayVals(i)(j).capacity) } } - //println(arrayVals.toSeq) - //val a = arrayVals.map({a:Array[Cell]=>a.toSeq}) - //for(k <- 0 to a.length - 1){println(a(k))} - //println(arrayVals.map({a:Array[Cell]=>a.toSeq}).toSeq) - //values = arrayVals.map({ a: Array[Cell] => a.toSeq }).toSeq - - values = Seq.tabulate(size,size){(i:Int,j:Int)=>Cell(arrayVals(i)(j).capacity,0,0) } + Seq.tabulate(size,size){(i:Int,j:Int)=>Cell(arrayVals(i)(j).capacity,0,0) } - values } } diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/container/PrefAttDiffusionContainer.scala b/model/src/main/scala/fr/iscpif/spacematters/model/container/PrefAttDiffusionContainer.scala index a93348a..b53cf0c 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/container/PrefAttDiffusionContainer.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/container/PrefAttDiffusionContainer.scala @@ -22,11 +22,6 @@ trait PrefAttDiffusionContainer <: Container { - var values : Seq[Seq[Cell]] = null - - - - /** * * @param rng @@ -78,8 +73,8 @@ trait PrefAttDiffusionContainer <: Container { //println("population : "+population) } - values = Seq.tabulate(size,size){(i:Int,j:Int)=>Cell(arrayVals(i)(j).capacity,0,0) } - values + Seq.tabulate(size,size){(i:Int,j:Int)=>Cell(arrayVals(i)(j).capacity,0,0) } + } diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala b/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala index 77b92d6..ccfbefb 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala @@ -16,7 +16,6 @@ */ package fr.iscpif.spacematters.model.initial -import fr.iscpif.schelling.quantity._ import fr.iscpif.spacematters.model.State import scala.util.Random diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala b/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala index fcd1fdf..a7f5421 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala @@ -16,8 +16,8 @@ */ package fr.iscpif.spacematters.model.initial -import fr.iscpif.schelling.quantity._ import fr.iscpif.spacematters.model._ +import fr.iscpif.spacematters.model.container._ import scala.util.Random diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/move/Moves.scala b/model/src/main/scala/fr/iscpif/spacematters/model/move/Moves.scala index be03c40..938ce20 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/move/Moves.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/move/Moves.scala @@ -16,7 +16,6 @@ */ package fr.iscpif.spacematters.model.move -import fr.iscpif.schelling.quantity._ import fr.iscpif.spacematters.model.{Position, State, Color} import scala.util.Random diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala b/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala index 63693e6..46e62d2 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala @@ -16,7 +16,7 @@ */ package fr.iscpif.spacematters.model.move -import fr.iscpif.schelling.quantity._ + import fr.iscpif.spacematters.model.{Position, State} trait Neighborhood { diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala b/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala index 74123bd..8e827db 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala @@ -16,7 +16,7 @@ */ package fr.iscpif.spacematters.model.move -import fr.iscpif.schelling.quantity._ + import fr.iscpif.spacematters.model.{Position, State, Color} case class Unsatisfied(position: Position, color: Color, number: Int) diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/stop/SpeilmanStop.scala b/model/src/main/scala/fr/iscpif/spacematters/model/stop/SpeilmanStop.scala index 2cbd40a..67dbd9c 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/stop/SpeilmanStop.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/stop/SpeilmanStop.scala @@ -16,7 +16,7 @@ */ package fr.iscpif.spacematters.model.stop -import fr.iscpif.schelling.quantity._ + import fr.iscpif.spacematters.model.{Schelling, State} import scala.util.{ Random, Try } diff --git a/model/src/main/scala/fr/iscpif/spacematters/model/test/TestContainer.scala b/model/src/main/scala/fr/iscpif/spacematters/model/test/TestContainer.scala index 9231cc3..789e821 100644 --- a/model/src/main/scala/fr/iscpif/spacematters/model/test/TestContainer.scala +++ b/model/src/main/scala/fr/iscpif/spacematters/model/test/TestContainer.scala @@ -1,10 +1,6 @@ package fr.iscpif.spacematters.model.test -import fr.iscpif.spacematters.model._ import fr.iscpif.spacematters.model.container._ -import fr.iscpif.spacematters.model.initial._ -import fr.iscpif.spacematters.model.move._ -import fr.iscpif.spacematters.model.stop._ import scala.util.Random @@ -14,12 +10,8 @@ object TestContainer extends App { implicit val rng = new Random - val simulation = new Schelling with RandomState with PrefAttDiffusionContainer with RandomMoves with SpeilmanStop { + val cont = new PrefAttDiffusionContainer{ 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 /*// exp Mixture params override def kernelRadius = 0.5 @@ -34,14 +26,11 @@ object TestContainer extends App { override def alphaAtt : Double = 1.1 } - // generate initial state - simulation.initialState(rng) + // generate instance of container + println(cont) + // an other + println(cont) - // print container - //simulation.printContainer - - println(simulation.values.flatten.map(_.capacity).max) - - println((System.currentTimeMillis()-t)/1000.0) + //println((System.currentTimeMillis()-t)/1000.0) } From 818d89ad07ce04d51a14808424faa4f37088b0c4 Mon Sep 17 00:00:00 2001 From: JusteRaimbault Date: Thu, 6 Aug 2015 17:53:56 +0200 Subject: [PATCH 5/6] Implemented slow indicators through fast convolution --- .../model/metric/Convolution.scala | 59 +++++++++++++++++++ .../spacematters/model/metric/package.scala | 54 +++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/Convolution.scala diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/Convolution.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/Convolution.scala new file mode 100644 index 0000000..db6f6d3 --- /dev/null +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/Convolution.scala @@ -0,0 +1,59 @@ +package fr.iscpif.spacematters.model.metric + +import org.apache.commons.math3.complex.Complex +import org.apache.commons.math3.transform.{ TransformType, DftNormalization, FastFourierTransformer } +import org.apache.commons.math3.util.MathArrays + +import scala.math._ + +object Convolution { + + /** + * Generic convol for double Arrays (in O(nlog(n)), using FFT) + * + * @param x + * @param k centered kernel + * @return y = x*k with y_i = \sum_{j=1}{|K|}{x_{i-j-|K|/2}*k_j} + */ + def convolution(x: Array[Double], k: Array[Double]): Array[Double] = { + val xl = pow(2.0, ceil(log(x.length) / log(2.0)) + 1) + val xp = x.padTo(x.length + (xl.toInt - x.length) / 2, 0.0).reverse.padTo(xl.toInt, 0.0).reverse + val kp = k.padTo(k.length + (xl.toInt - k.length) / 2, 0.0).reverse.padTo(xl.toInt, 0.0).reverse + val tr = new FastFourierTransformer(DftNormalization.STANDARD) + val ftx = tr.transform(xp, TransformType.FORWARD) + val ftk = tr.transform(kp, TransformType.FORWARD) + val real = MathArrays.ebeSubtract(MathArrays.ebeMultiply(ftx.map { z => z.getReal }, ftk.map { z => z.getReal }), MathArrays.ebeMultiply(ftx.map { z => z.getImaginary }, ftk.map { z => z.getImaginary })) + val im = MathArrays.ebeAdd(MathArrays.ebeMultiply(ftx.map { z => z.getReal }, ftk.map { z => z.getImaginary }), MathArrays.ebeMultiply(ftx.map { z => z.getImaginary }, ftk.map { z => z.getReal })) + val trinv = tr.transform(Array.tabulate(real.length) { i => new Complex(real(i), im(i)) }, TransformType.INVERSE).map { z => z.getReal } + trinv.splitAt(trinv.length - x.length / 2)._2 ++ trinv.splitAt(x.length - x.length / 2)._1 + } + + /** + * Square convol (for tests) + * + * @param x + * @param k + * @return + */ + def directConvol(x: Array[Double], k: Array[Double]): Array[Double] = { + val kl = k.length + val xpadded = x.padTo(x.length + kl, 0.0).reverse.padTo(x.length + 2 * kl, 0.0).reverse + Array.tabulate(x.length + k.length) { i => MathArrays.ebeMultiply(k.reverse, xpadded.splitAt(i + 1)._2.splitAt(k.length)._1).sum } + } + + /** + * 2D convolution + * Using bijection [|1,N|]2 ~ [|1,N|] by flattening, after having good paddling + * + * @param x + * @param k + */ + def convolution2D(x: Array[Array[Double]], k: Array[Array[Double]]): Array[Array[Double]] = { + val xpad = x.map { row => row.padTo(2 * (row.length / 2) + 1 + k(0).length, 0.0).reverse.padTo(2 * (row.length / 2) + 1 + 2 * k(0).length, 0.0).reverse }.padTo(2 * (x.length / 2) + 1 + k.length, Array.fill(2 * (x(0).length / 2) + 1 + 2 * k(0).length) { 0.0 }).reverse.padTo(2 * (x.length / 2) + 1 + 2 * k.length, Array.fill(2 * (x(0).length / 2) + 1 + 2 * k(0).length) { 0.0 }) + val xpos = Array.fill(x.length, x(0).length) { 1.0 }.map { row => row.padTo(2 * (row.length / 2) + 1 + k(0).length, 0.0).reverse.padTo(2 * (row.length / 2) + 1 + 2 * k(0).length, 0.0).reverse }.padTo(2 * (x.length / 2) + 1 + k.length, Array.fill(2 * (x(0).length / 2) + 1 + 2 * k(0).length) { 0.0 }).reverse.padTo(2 * (x.length / 2) + 1 + 2 * k.length, Array.fill(2 * (x(0).length / 2) + 1 + 2 * k(0).length) { 0.0 }).flatten + val kpad = k.map { row => row.padTo(row.length + (xpad(0).length - row.length) / 2, 0.0).reverse.padTo(xpad(0).length, 0.0).reverse }.padTo(k.length + (xpad.length - k.length) / 2, Array.fill(xpad(0).length) { 0.0 }).reverse.padTo(xpad.length, Array.fill(xpad(0).length) { 0.0 }) + val flatconv = convolution(xpad.flatten, kpad.flatten) + flatconv.zipWithIndex.filter { case (_, j) => xpos(j) > 0 }.map { case (d, _) => d }.sliding(x(0).length, x.length).toArray.reverse + } + +} diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala index 9ad1ff5..38a71c1 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala @@ -190,4 +190,58 @@ package object metric { if i != oi || j != oj } yield state(i + oi)(j + oj) + + + + /** + * Moran index using fast convolution. + * + * @param matrix + * @return + */ + def moran_convol(matrix: Matrix[T],quantity: Quantity[T]): Double = { + val conf = matrix.map { row => row.map(quantity).toArray }.toArray + val n = conf.length + val flatConf = conf.flatten + val popMean = flatConf.sum / flatConf.length + val centeredConf = conf.map { r => r.map { d => d - popMean } } + val variance = MathArrays.ebeMultiply(centeredConf.flatten, centeredConf.flatten).sum + val weights = spatialWeights(2 * n - 1) + val totWeight = Convolution.convolution2D(Array.fill(n, n) { 1.0 }, weights).flatten.sum + flatConf.length / (totWeight * variance) * MathArrays.ebeMultiply(centeredConf.flatten, Convolution.convolution2D(centeredConf, weights).flatten).sum + } + + def spatialWeights(n: Int): Array[Array[Double]] = { + Array.tabulate(n, n) { (i, j) => if (i == n / 2 && j == n / 2) 0.0 else 1 / Math.sqrt((i - n / 2) * (i - n / 2) + (j - n / 2) * (j - n / 2)) } + } + + /** + * Mean distance using fast convolution. + * + * @param matrix + * @return + */ + def distance_convol(matrix: Matrix[T],quantity: Quantity[T]): Double = { + val conf = matrix.map { row => row.map(quantity).toArray }.toArray + val totPop = conf.flatten.sum + val dmat = distanceMatrix(2 * conf.length - 1) + val conv = Convolution.convolution2D(conf, dmat) + math.sqrt(math.Pi) / (conf.length * totPop * totPop) * MathArrays.ebeMultiply(conv.flatten, conf.flatten).sum + } + + /** + * Distance kernel + * + * @param n + * @return + */ + def distanceMatrix(n: Int): Array[Array[Double]] = { + Array.tabulate(n, n) { (i, j) => Math.sqrt((i - n / 2) * (i - n / 2) + (j - n / 2) * (j - n / 2)) } + } + + + + + + } From 9023119c6b3cbd5f5cad073e6894620d862c72ff Mon Sep 17 00:00:00 2001 From: JusteRaimbault Date: Fri, 14 Aug 2015 15:06:13 +0200 Subject: [PATCH 6/6] minor changes --- .../fr/iscpif/spacematters/model/Schelling.scala | 1 - .../fr/iscpif/spacematters/model/Simulation.scala | 2 +- .../spacematters/model/initial/InitialState.scala | 1 - .../spacematters/model/initial/RandomState.scala | 1 - .../iscpif/spacematters/model/metric/package.scala | 12 ++---------- .../spacematters/model/move/Neighborhood.scala | 1 - .../spacematters/model/move/Unsatisfieds.scala | 1 - 7 files changed, 3 insertions(+), 16 deletions(-) diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala index badb399..d821370 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/Schelling.scala @@ -16,7 +16,6 @@ */ package fr.iscpif.spacematters.model - import fr.iscpif.spacematters.model.initial._ import fr.iscpif.spacematters.model.move._ diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala index 6d47e89..e822aad 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/Simulation.scala @@ -24,7 +24,7 @@ object Simulation extends App { 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 diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala index 3132a9d..24925ab 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/InitialState.scala @@ -16,7 +16,6 @@ */ package fr.iscpif.spacematters.model.initial - import fr.iscpif.spacematters.model._ import scala.util.Random diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala index cb0a2df..8e70426 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/initial/RandomState.scala @@ -27,7 +27,6 @@ trait RandomState <: InitialState with Container { self: Schelling => def initialState(implicit rng: Random) = { - val cells = container(rng) val totalCapacity = cells.flatten.map(_.capacity).sum diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala index 38a71c1..a03da37 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/metric/package.scala @@ -190,16 +190,13 @@ package object metric { if i != oi || j != oj } yield state(i + oi)(j + oj) - - - /** * Moran index using fast convolution. * * @param matrix * @return */ - def moran_convol(matrix: Matrix[T],quantity: Quantity[T]): Double = { + def moran_convol(matrix: Matrix[T], quantity: Quantity[T]): Double = { val conf = matrix.map { row => row.map(quantity).toArray }.toArray val n = conf.length val flatConf = conf.flatten @@ -221,7 +218,7 @@ package object metric { * @param matrix * @return */ - def distance_convol(matrix: Matrix[T],quantity: Quantity[T]): Double = { + def distance_convol(matrix: Matrix[T], quantity: Quantity[T]): Double = { val conf = matrix.map { row => row.map(quantity).toArray }.toArray val totPop = conf.flatten.sum val dmat = distanceMatrix(2 * conf.length - 1) @@ -239,9 +236,4 @@ package object metric { Array.tabulate(n, n) { (i, j) => Math.sqrt((i - n / 2) * (i - n / 2) + (j - n / 2) * (j - n / 2)) } } - - - - - } diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala index d529363..ca58940 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Neighborhood.scala @@ -16,7 +16,6 @@ */ package fr.iscpif.spacematters.model.move - import fr.iscpif.spacematters.model._ trait Neighborhood { diff --git a/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala b/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala index 961bf00..5e40347 100644 --- a/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala +++ b/scala/model/src/main/scala/fr/iscpif/spacematters/model/move/Unsatisfieds.scala @@ -18,7 +18,6 @@ package fr.iscpif.spacematters.model.move import fr.iscpif.spacematters.model._ - case class Unsatisfied(position: Position, color: Color, number: Int) trait Unsatisfieds <: Neighborhood {