Skip to content

Commit 6177c98

Browse files
Multiscalemicro:model_dynamics
1 parent ec435d7 commit 6177c98

4 files changed

Lines changed: 101 additions & 22 deletions

File tree

‎library/src/main/scala/org/openmole/spatialdata/application/multimodelmacro/RealData.scala‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ object RealData {
3838
distancesFile: String,
3939
datesFile: String): (Matrix, Matrix, Array[Double]) = {
4040
implicit val m: MatrixImplementation = Matrix.defaultImplementation
41-
rng.setSeed(seed)
4241

4342
// load populations, dates, distance matrix
4443
val populationMatrix: Matrix = Matrix(CSV.readMat(populationsFile))

‎library/src/main/scala/org/openmole/spatialdata/application/multimodelmacro/RunSDG.scala‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object RunSDG extends App {
2222

2323
// real data setup
2424
val initialState = RealData.setupRealData(
25-
25+
"","","" //TODO
2626
)
2727

2828
val result = SDG.runMultiModelMacro(
@@ -55,7 +55,7 @@ object RunSDG extends App {
5555

5656
utils.log(s"Indicators: Emissions = ${SDG.cumulatedFlows(result)}; Innovation = ${- SDG.averageUtility(result)}; Infrastructure = ${SDG.averageDistance(result)}; Eco inequality = ${SDG.giniEconomicWealth(result)}; Wealth = ${SDG.averageWealth(result)}")
5757

58-
val realresult: RealData.Result = RealData.Result(result)
58+
val realresult: RealData.Result = RealData.Result(result.asInstanceOf[MultiMacroResult])
5959

6060
utils.log(s"Fit on populations : logmse = ${realresult.logmse} ; mselog = ${realresult.mselog}")
6161

‎library/src/main/scala/org/openmole/spatialdata/application/multimodelmacro/SDG.scala‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ object SDG {
9393
// note: constructor are a mess: legacy vs mutation model, no proper for mutation
9494
// initial innov utility is 1
9595
val distrib = innovationUtilityDistrib match {case "normal" => InnovationUtilityNormalDistribution(); case "log-normal" => InnovationUtilityLogNormalDistribution()}
96-
val innovModel = Innovation(populationMatrix,dmat,dates,rng,0.0,innovationWeight,innovationGravityDecay,innovationInnovationDecay,
96+
val innovModel = Innovation(population,distances,dates,rng,0.0,innovationWeight,innovationGravityDecay,innovationInnovationDecay,
9797
mutationInnovation(_,_,_, innovationMutationRate, innovationNewInnovationHierarchy, innovationEarlyAdoptersRate, innovationUtilityStd, distrib),
9898
1.0
9999
)
@@ -102,12 +102,12 @@ object SDG {
102102
// eco exchanges - ! add gravitypotentials in eco state (total emission: cumulated interactions across models)
103103
// ! issue: not same unit for innov / eco (supply - demand gravity potentials) -> should compute something equivalent?
104104
// ! marius weight? - rescale pop updates?
105-
val ecoModel = EconomicExchanges(populationMatrix, dmat, dates, ecoWeight, ecoSizeEffectOnDemand, ecoSizeEffectOnSupply, ecoGravityDecay, ecoWealthToPopulationExponent, ecoPopulationToWealthExponent)
105+
val ecoModel = EconomicExchanges(population, distances, dates, ecoWeight, ecoSizeEffectOnDemand, ecoSizeEffectOnSupply, ecoGravityDecay, ecoWealthToPopulationExponent, ecoPopulationToWealthExponent)
106106
val ecoInitialState = EconomicExchanges.initialState(ecoModel)
107107

108108
// coevolution
109109
// rq: flows also in other unit (pop rescaled) -> must compute pop-based only for comparability
110-
val coevolModel = Coevolution(populationMatrix, Array(dmat), EmptyMatrix(), dates, 0.0, coevolWeight, coevolGamma, coevolGravityDecay,
110+
val coevolModel = Coevolution(population, Array(distances), EmptyMatrix(), dates, 0.0, coevolWeight, coevolGamma, coevolGravityDecay,
111111
0.0, 1.0, 1.0, coevolNetworkGmax, coevolNetworkExponent, coevolNetworkThresholdQuantile)
112112
val coevolInitialState = Coevolution.initialState(coevolModel)
113113

‎library/src/main/scala/org/openmole/spatialdata/application/multiscalemicro/MultiscaleMicro.scala‎

Lines changed: 96 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)