@@ -3,13 +3,13 @@ package eighties.h24
33import org .locationtech .jts .geom .{Coordinate , Envelope }
44import org .locationtech .jts .index .strtree .STRtree
55import eighties .h24 .tools .random .multinomial
6- import eighties .h24 .social ._
6+ import eighties .h24 .social .*
77import space .{Attraction , Index , Location , World }
8- import eighties .h24 .generation .{LCell , dayTimeSlice , nightTimeSlice }
8+ import eighties .h24 .generation .{LCell , dayTimeSlice , nightTimeSlice , timeSlices }
99import monocle .function .all .index
1010import monocle .{Lens , Traversal }
11- import tools .random ._
12- import monocle ._
11+ import tools .random .*
12+ import monocle .*
1313
1414import scala .reflect .ClassTag
1515import scala .util .Random
@@ -19,24 +19,22 @@ object dynamic {
1919 import MoveMatrix ._
2020
2121 def reachable [T ](index : Index [T ]): Seq [(Int , Int )] =
22- for {
22+ for
2323 i <- 0 until index.sideI
2424 j <- 0 until index.sideJ
2525 if ! index.cells(i)(j).isEmpty
26- } yield (i, j)
26+ yield (i, j)
2727
28- def randomMove [I : ClassTag ](world : World [I ], timeSlice : TimeSlice , ratio : Double , location : Lens [I , Location ], stableDestinations : I => Map [TimeSlice , Location ], random : Random ): World [I ] = {
28+ def stableDestinationOrRandomMove [I : ClassTag ](world : World [I ], timeSlice : TimeSlice , location : Lens [I , Location ], stableDestinations : I => Map [TimeSlice , Location ], random : Random ): World [I ] =
2929 val reach = reachable(Index .indexIndividuals(world, location.get))
3030 val rSize = reach.size
31- def randomLocation = location.modify(l => if (random.nextDouble() < ratio) reach(random.nextInt(rSize)) else l )
31+ def randomLocation = location.replace( reach(random.nextInt(rSize)))
3232 def move (individual : I ) = stableLocationOrMove(individual, timeSlice, stableDestinations, location, randomLocation)
3333 (World .allIndividuals[I ] modify move) (world)
34- }
3534
36- def goBackHome [W , I ](world : W , allIndividuals : Traversal [W , I ], location : Lens [I , Location ], home : I => Location ): W = {
37- def m = (individual : I ) => location.set (home(individual))(individual)
35+ def goBackHome [W , I ](world : W , allIndividuals : Traversal [W , I ], location : Lens [I , Location ], home : I => Location ): W =
36+ def m = (individual : I ) => location.replace (home(individual))(individual)
3837 (allIndividuals modify m)(world)
39- }
4038
4139 object MoveMatrix {
4240
@@ -232,92 +230,114 @@ object dynamic {
232230
233231 }
234232
235- def moveFlowDefaultOnOtherSex [I ](cellMoves : Cell , individual : I , socialCategory : I => AggregatedSocialCategory ) /* moves: MoveMatrix.CellMatrix, individualInCel: Individual)*/ = {
233+ def moveFlowDefaultOnOtherSex [I ](cellMoves : Cell , individual : I , socialCategory : I => AggregatedSocialCategory ) /* moves: MoveMatrix.CellMatrix, individualInCel: Individual)*/ =
236234 // val location = Individual.location.get(individual)
237235 // val cellMoves = moves(location._1)(location._2)
238236 val aggregatedCategory = socialCategory(individual)
239237 def myCategory = cellMoves.get(aggregatedCategory)
240238 def noSex = cellMoves.find { case (c, _) => Focus [AggregatedSocialCategory ](_.age).get(c) == Focus [AggregatedSocialCategory ](_.age).get(aggregatedCategory) && c.education == aggregatedCategory.education }.map(_._2)
241239 myCategory orElse noSex
242- }
243240
244241 def sampleDestinationInMoveMatrix [I ](cellMoves : Cell , individual : I , socialCategory : I => AggregatedSocialCategory , random : Random ) =
245- moveFlowDefaultOnOtherSex(cellMoves, individual, socialCategory).flatMap { m =>
246- if (m.isEmpty) None else Some (multinomial(m.map{ m => MoveMatrix .Move .location.get(m) -> Focus [MoveMatrix .Move ](_.ratio).get(m).toDouble })(random))
247- }
242+ moveFlowDefaultOnOtherSex(cellMoves, individual, socialCategory).flatMap: m =>
243+ if m.isEmpty
244+ then None
245+ else
246+ Some :
247+ multinomial(m.map{ m => MoveMatrix .Move .location.get(m) -> Focus [MoveMatrix .Move ](_.ratio).get(m).toDouble })(using random)
248248
249249 def stableLocationOrMove [I ](individual : I , timeSlice : TimeSlice , stableDestinations : I => Map [TimeSlice , Location ], location : Lens [I , Location ], move : I => I ) =
250- stableDestinations(individual).get(timeSlice) match {
250+ stableDestinations(individual).get(timeSlice) match
251251 case None => move(individual)
252252 case Some (stableDestination) => location.set(stableDestination)(individual)
253- }
254253
255- def moveInMoveMatrix [I : ClassTag ](world : World [I ], locatedCell : LocatedCell , timeSlice : TimeSlice , stableDestination : I => Map [TimeSlice , Location ], location : Lens [I , Location ], home : I => Location , socialCategory : I => AggregatedSocialCategory , random : Random ): World [I ] = {
256- def sampleMoveInMatrix [J ](cellMoves : Cell , location : Lens [J , Location ], socialCategory : J => AggregatedSocialCategory )(individual : J ) =
257- sampleDestinationInMoveMatrix(cellMoves, individual, socialCategory, random) match {
258- case Some (destination) => location.set(destination)(individual)
254+
255+ def stableDestinationOrMoveInMoveMatrix [I : ClassTag ](
256+ world : World [I ],
257+ locatedCell : LocatedCell ,
258+ timeSlice : TimeSlice ,
259+ stableDestination : I => Map [TimeSlice , Location ],
260+ location : Lens [I , Location ],
261+ home : I => Location ,
262+ socialCategory : I => AggregatedSocialCategory ,
263+ randomRatio : Double ,
264+ random : Random ): World [I ] =
265+
266+ def sampleMoveInMatrix (cellMoves : Cell , location : Lens [I , Location ], socialCategory : I => AggregatedSocialCategory )(individual : I ): I =
267+ sampleDestinationInMoveMatrix(cellMoves, individual, socialCategory, random) match
268+ case Some (destination) => location.replace(destination)(individual)
259269 case None => individual
260- }
270+
271+
272+ lazy val reach = reachable(Index .indexIndividuals(world, location.get))
273+ lazy val rSize = reach.size
274+
275+ def randomMove (location : Lens [I , Location ], random : Random ) =
276+ location.replace(reach(random.nextInt(rSize)))
277+
278+ def move (cellMoves : => Cell , location : Lens [I , Location ], socialCategory : I => AggregatedSocialCategory , random : Random ) =
279+ def stableOrMoveInMatrix (individual : I ) = stableLocationOrMove(individual, timeSlice, stableDestination, location, sampleMoveInMatrix(cellMoves, location, socialCategory))
280+
281+ if randomRatio <= 0.0
282+ then stableOrMoveInMatrix
283+ else
284+ if random.nextDouble() < randomRatio
285+ then randomMove(location, random)
286+ else stableOrMoveInMatrix
261287
262288 val newIndividuals = Array .ofDim[I ](world.individuals.length)
263289 var index = 0
264290
265- for {
291+ for
266292 (line, i) <- Focus [Index [I ]](_.cells).get(Index .indexIndividuals(world, home)).zipWithIndex
267293 (individuals, j) <- line.zipWithIndex
268- } {
294+ do
269295 lazy val cell = locatedCell(timeSlice, i, j)
270- for {
296+ for
271297 individual <- individuals
272- } {
273- newIndividuals(index) = stableLocationOrMove(individual, timeSlice, stableDestination, location, sampleMoveInMatrix( cell, location, socialCategory) )
298+ do
299+ newIndividuals(index) = move( cell, location, socialCategory, random)(individual )
274300 index += 1
275- }
276- }
301+
277302
278303 Focus [World [I ]](_.individuals).set(newIndividuals)(world)
279- }
280304
281- def assignRandomDayLocation [I : ClassTag ](world : World [I ], locatedCell : LocatedCell , stableDestination : Lens [I , Map [TimeSlice , Location ]], location : I => Location , home : I => Location , socialCategory : I => AggregatedSocialCategory , rng : Random ) = {
305+ def assignRandomDayLocation [I : ClassTag ](world : World [I ], locatedCell : LocatedCell , stableDestination : Lens [I , Map [TimeSlice , Location ]], location : I => Location , home : I => Location , socialCategory : I => AggregatedSocialCategory , rng : Random ) =
282306 val newIndividuals = Array .ofDim[I ](world.individuals.length)
283307 var index = 0
284308
285- for {
309+ for
286310 (line, i) <- Focus [Index [I ]](_.cells).get(Index .indexIndividuals(world, location)).zipWithIndex
287311 (individuals, j) <- line.zipWithIndex
288- } {
312+ do
289313 val workTimeMovesFromCell = locatedCell(dayTimeSlice, i, j)
290314
291315 assert(workTimeMovesFromCell != null )
292316
293- for {
317+ for
294318 individual <- individuals
295- } {
319+ do
296320 def newIndividual =
297321 dynamic.sampleDestinationInMoveMatrix(workTimeMovesFromCell, individual, socialCategory, rng) match {
298322 case Some (d) => stableDestination.modify(_ + (dayTimeSlice -> d))(individual)
299323 case None => stableDestination.modify(_ + (dayTimeSlice -> home(individual)))(individual)
300324 }
301325 newIndividuals(index) = newIndividual
302326 index += 1
303- }
304- }
305327
306328 Focus [World [I ]](_.individuals).set(newIndividuals)(world)
307- }
308329
309330 def assignFixNightLocation [I : ClassTag ](world : World [I ], stableDestination : Lens [I , Map [TimeSlice , Location ]], home : I => Location ) =
310331 World .allIndividuals[I ].modify { individual => stableDestination.modify(_ + (nightTimeSlice -> home(individual)))(individual) } (world)
311332
312- def randomiseLocation [I : ClassTag ](world : World [I ], location : I => Location , home : Lens [I , Location ], random : Random ) = {
333+ def randomiseLocation [I : ClassTag ](world : World [I ], location : I => Location , home : Lens [I , Location ], random : Random ) =
313334 val reach = reachable(Index [I ](world.individuals.iterator, location, world.sideI, world.sideJ))
314335 val reachSize = reach.size
315336
316337 def assign (individual : I ): I =
317338 home.set(reach(random.nextInt(reachSize))) (individual)
318339
319340 (World .allIndividuals[I ] modify assign)(world)
320- }
321341
322342 def generateAttractions [I : ClassTag ](world : World [I ], proportion : Double , location : I => Location , random : Random ) = {
323343 val reach = reachable(Index .indexIndividuals(world, location))
0 commit comments