@@ -112,7 +112,16 @@ object MultiscaleMicro {
112112 * @param positioning positioning function
113113 * @return
114114 */
115- def addBuildings (currentState : State , numberToAdd : Int , buildingWidth : Double , buildingHeight : Int , shareHousing : Double , streetBuffer : Double , positioning : State => (Double , Double ), patchSize : Double , lambdaDensity : Double )(implicit rng : Random ): State = {
115+ def addBuildings (currentState : State ,
116+ numberToAdd : Int ,
117+ buildingWidth : Double ,
118+ buildingHeight : Int ,
119+ shareHousing : Double ,
120+ streetBuffer : Double ,
121+ positioning : State => (Double , Double ),
122+ patchSize : Double ,
123+ lambdaDensity : Double
124+ )(implicit rng : Random ): State = {
116125
117126 val (xmin,xmax,ymin,ymax) = bbox(currentState)
118127 val (x, y) = positioning(currentState)
@@ -231,7 +240,7 @@ object MultiscaleMicro {
231240 def initialGrid (initialNetwork : TransportationNetwork , patchSize : Double , lambdaDensity : Double ): Grid = {
232241 val nodesidseq = initialNetwork.network.nodes.map(_.id).toSeq
233242 // each node is the center of a patch
234- val (distToStationsMap, distToCentresMap) = distances(initialNetwork)
243+ val (distToStationsMap, distToCentresMap) = TransportationNetwork . distances(initialNetwork)
235244 val coordsMap = initialNetwork.network.nodes.map(n => (n.id,n.position)).toMap
236245 val empty = emptyGrid(nodesidseq, coordsMap, distToStationsMap, distToCentresMap, patchSize)
237246 aggregateBuildingsToGrid(empty, Polygons .empty, lambdaDensity)
@@ -257,18 +266,7 @@ object MultiscaleMicro {
257266 )
258267 }
259268
260- /**
261- * compute distance from nodes to stations and centres
262- * indices are not needed as nw nodes are fixed
263- * @param nw network
264- * @return maps Node id => distance for stations and centres
265- */
266- def distances (nw : TransportationNetwork ): (Map [Int ,Double ],Map [Int ,Double ]) = {
267- val nodesseq = nw.network.nodes.toSeq
268- val distToStationsMap : Map [Int ,Double ] = nw.network.shortestPathTo(nodesseq,nw.stations).toSeq.groupMap(_._1._1)(_._2._3).map{case (n,dists) => (n.id, dists.min)}
269- val distToCentresMap : Map [Int ,Double ] = nw.network.shortestPathTo(nodesseq,nw.centres).toSeq.groupMap(_._1._1)(_._2._3).map{case (n,dists) => (n.id, dists.min)}
270- (distToStationsMap, distToCentresMap)
271- }
269+
272270
273271 /**
274272 * recompute counts and densities in grid cells given buildings
@@ -324,6 +322,24 @@ object MultiscaleMicro {
324322 }
325323
326324
325+ def updateDensityVariables (model : MultiscaleMicro , state : State ): State = {
326+ state.copy(
327+ grid = aggregateBuildingsToGrid(state.grid, state.buildings, model.lambdaDensity)
328+ )
329+ }
330+
331+ /**
332+ * Recompute distance and density variables
333+ * @param model model
334+ * @param state state
335+ * @return
336+ */
337+ def updateVariables (model : MultiscaleMicro , state : State ): State = {
338+ val updatedNetworkDistances = TransportationNetwork .updateNetworkDistances(state)
339+ updateDensityVariables(model, updatedNetworkDistances)
340+ }
341+
342+
327343 }
328344
329345 /**
@@ -370,6 +386,48 @@ object MultiscaleMicro {
370386 utils.log(s " Network nodes coordinates in [ ${nw.nodes.map(_.position._1).min}, ${nw.nodes.map(_.position._1).max}] x [ ${nw.nodes.map(_.position._2).min}, ${nw.nodes.map(_.position._2).max}] " )
371387 TransportationNetwork (nw, centres, initialTrLinks.toSeq, centres)
372388 }
389+
390+
391+ /**
392+ * compute distance from nodes to stations and centres
393+ * indices are not needed as nw nodes are fixed
394+ * @param nw network
395+ * @return maps Node id => distance for stations and centres
396+ */
397+ def distances (nw : TransportationNetwork ): (Map [Int ,Double ],Map [Int ,Double ]) = {
398+ val nodesseq = nw.network.nodes.toSeq
399+ val distToStationsMap : Map [Int ,Double ] = nw.network.shortestPathTo(nodesseq,nw.stations).toSeq.groupMap(_._1._1)(_._2._3).map{case (n,dists) => (n.id, dists.min)}
400+ val distToCentresMap : Map [Int ,Double ] = nw.network.shortestPathTo(nodesseq,nw.centres).toSeq.groupMap(_._1._1)(_._2._3).map{case (n,dists) => (n.id, dists.min)}
401+ (distToStationsMap, distToCentresMap)
402+ }
403+
404+ /**
405+ * Recompute network distances
406+ * @param state state with updated network but not distances
407+ * @return
408+ */
409+ def updateNetworkDistances (state : State ): State = {
410+ val nodesidseq = state.network.network.nodes.map(_.id).toSeq
411+ val (distToStationsMap, distToCentresMap) = distances(state.network)
412+ val updatedGrid = state.grid.copy(
413+ patchDistancesToNetwork = nodesidseq.map(distToStationsMap(_)),
414+ patchDistancesToCentre = nodesidseq.map(distToCentresMap(_))
415+ )
416+ state.copy(grid= updatedGrid)
417+ }
418+
419+ /**
420+ * Add long distance links to the network
421+ * @param model model
422+ * @param state state
423+ * @return
424+ */
425+ def evolveNetwork (model: MultiscaleMicro , state : State ): State = {
426+ // TODO
427+ state
428+ }
429+
430+
373431 }
374432
375433
@@ -397,6 +455,21 @@ object MultiscaleMicro {
397455 // sealed trait DeveloperAgentsSetupMode
398456 // case object DeveloperAgentsUniformSetup extends DeveloperAgentsSetupMode
399457 // case object DeveloperAgentsHeterogenousSetup extends DeveloperAgentsSetupMode
458+
459+
460+ /**
461+ * Core function simulating microscopic dynamics of developers
462+ * -> compute utilities
463+ * -> compute a positioning function for addBuildings
464+ * @param model model
465+ * @param state state
466+ * @return
467+ */
468+ def developerAgentsProjects (model : MultiscaleMicro , state : State ): State = {
469+
470+ state
471+ }
472+
400473 }
401474
402475 case class Result (
@@ -411,8 +484,15 @@ object MultiscaleMicro {
411484 * @param state state
412485 * @return
413486 */
414- def step (model : MultiscaleMicro , state : State ): State = {
415- state
487+ def step (model : MultiscaleMicro , state : State )(implicit rng : Random ): State = {
488+ def oneStepBuildings (state : State ): State = DeveloperAgent .developerAgentsProjects(model, state)
489+ // state.copy(
490+ // buildings = State.addBuildings(// behavior of developer agents -> discrete choices
491+ // )(rng))
492+ val withNewBuildings = Iterator .iterate(state)(oneStepBuildings).take(model.mesoStepInterval).toList.last
493+ val withUpdatedDensities = Grid .updateDensityVariables(model, withNewBuildings)
494+ val withUpdatedNetwork = TransportationNetwork .evolveNetwork(model, withUpdatedDensities)
495+ Grid .updateVariables(model, withUpdatedNetwork) // in practice last step
416496 }
417497
418498 /**
0 commit comments