[add][fix] added output that can be run parallel to the simulation
- the output sleep waits for a full tick result - [fix] fixed the simulation to pass the correct gt parent if exists
This commit is contained in:
@@ -1,13 +1,15 @@
|
|||||||
package scim.components
|
package scim.components
|
||||||
|
|
||||||
import scim.datastruct.SharedMemory
|
import scim.datastruct.{Cell, Group, SensorResult, SharedMemory}
|
||||||
|
|
||||||
class Output(sharedMemory: SharedMemory) extends Runnable {
|
class Output(sharedMemory: SharedMemory) extends Runnable {
|
||||||
def run(): Unit = {
|
def run(): Unit = {
|
||||||
outputData()
|
val output = sharedMemory.output
|
||||||
|
(0 until output.size, output).zipped.foreach((time, result) => outputData(time, result.watch()))
|
||||||
}
|
}
|
||||||
|
|
||||||
def outputData(): Unit = {
|
def outputData(time: Int, output: Map[Cell, Map[Group, Vector[SensorResult]]]): Unit = {
|
||||||
|
println("TICK: " + time)
|
||||||
|
println(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Simulation(config: Configuration) {
|
|||||||
private val sharedMemory = config.sharedMemory
|
private val sharedMemory = config.sharedMemory
|
||||||
private val sharedConfig = sharedMemory.config
|
private val sharedConfig = sharedMemory.config
|
||||||
private val cells = config.cells
|
private val cells = config.cells
|
||||||
|
val output = sharedMemory.output
|
||||||
|
|
||||||
|
|
||||||
def start(): Unit = {
|
def start(): Unit = {
|
||||||
@@ -38,6 +39,8 @@ class Simulation(config: Configuration) {
|
|||||||
} else {
|
} else {
|
||||||
cells.foreach(simCell)
|
cells.foreach(simCell)
|
||||||
}
|
}
|
||||||
|
// broadcast the results
|
||||||
|
output(time.time).broadcast(sensorResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def simGroups(time: Time, cell: Cell, groups: Map[Group, List[(Group, Sensor, Option[GroundTruth])]], prevTruths: Map[Group, Truth], resultTruths: Map[Group, Truth], resultSensors: Map[Group, Vector[SensorResult]]): Unit = {
|
private def simGroups(time: Time, cell: Cell, groups: Map[Group, List[(Group, Sensor, Option[GroundTruth])]], prevTruths: Map[Group, Truth], resultTruths: Map[Group, Truth], resultSensors: Map[Group, Vector[SensorResult]]): Unit = {
|
||||||
@@ -46,12 +49,14 @@ class Simulation(config: Configuration) {
|
|||||||
// at the same time as the parent in a different thread. This would allow the child to start running as soon
|
// at the same time as the parent in a different thread. This would allow the child to start running as soon
|
||||||
// as the ground truth is calculated in the parent and doesn't have have to wait for the sensors to finish.
|
// as the ground truth is calculated in the parent and doesn't have have to wait for the sensors to finish.
|
||||||
// Any subsequent children can start in the same manner, when their parent is done with the ground truth.
|
// Any subsequent children can start in the same manner, when their parent is done with the ground truth.
|
||||||
|
// this would require sharedConfig.cellThreadPool * 2 additional threads
|
||||||
// :
|
// :
|
||||||
// only run ground truth in list, have sensors in their respective groups
|
// another option would be to calculate all ground truths within a list first and than parellize the sensor list
|
||||||
// requires groups to be split into two elements: sensor and ground truth
|
def simGroup(input: (Group, List[(Group, Sensor, Option[GroundTruth])])): Unit = {
|
||||||
// Tuple2(Map[Group, list[(Group, Option[GroundTruth])]], Map[Group, Sensor])
|
val group = input._1
|
||||||
def simGroup(group: (Group, List[(Group, Sensor, Option[GroundTruth])])): Unit = {
|
val truthGroup = group.getParentOrGroup // make sure the correct ground truth gets passed
|
||||||
group._2.foreach(element => simulate(time, cell, prevTruths(group._1), resultTruths(group._1), resultSensors(group._1), element))
|
val groupList = input._2
|
||||||
|
groupList.foreach(element => simulate(time, cell, prevTruths(truthGroup), resultTruths(group), resultSensors(group), element))
|
||||||
}
|
}
|
||||||
if(sharedConfig.parGroup != 0 && cells.size >= sharedConfig.parGroup ) {
|
if(sharedConfig.parGroup != 0 && cells.size >= sharedConfig.parGroup ) {
|
||||||
val groupList = groups.par
|
val groupList = groups.par
|
||||||
|
|||||||
@@ -15,9 +15,13 @@ case class Time(time: Int, duration: Int){
|
|||||||
def get: Int = { time }
|
def get: Int = { time }
|
||||||
}
|
}
|
||||||
|
|
||||||
case class SharedMemory( sensor: Map[Time, Map[Cell, Map[Group, Vector[SensorResult]]]],
|
// while it would seem convinient to just throw the sensors/behaviours as value into these
|
||||||
groundTruth: Map[Time, Map[Cell, Map[Group, Truth]]],
|
// and have them just hold their value, this would get messy with dependencies:
|
||||||
config: SimulationConfig, cache: Boolean = true) {
|
// Map[Time, Map[Cell, Map[Group, List(Group, Truth)]]] and getting the result for the sensor
|
||||||
|
case class SharedMemory(sensor: Map[Time, Map[Cell, Map[Group, Vector[SensorResult]]]],
|
||||||
|
groundTruth: Map[Time, Map[Cell, Map[Group, Truth]]],
|
||||||
|
config: SimulationConfig,
|
||||||
|
output: Vector[BroadcastObject[Map[Cell, Map[Group, Vector[SensorResult]]]]]) {
|
||||||
// This could be spatially optimized to have a function to invoke a new simulation tick
|
// This could be spatially optimized to have a function to invoke a new simulation tick
|
||||||
// a template of Map[SensorID, SensorResult] would have to be kept and deep copied when
|
// a template of Map[SensorID, SensorResult] would have to be kept and deep copied when
|
||||||
// another tick is simulated. this won't work for ground truth, as it may already be defined
|
// another tick is simulated. this won't work for ground truth, as it may already be defined
|
||||||
@@ -99,6 +103,8 @@ case class Behaviour(behaviour: BehaviourVector){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// while the gt depends on the cell, the object itself does not
|
||||||
|
// unlike the sensor which is unique due to its count for each cell
|
||||||
case class GroundTruth(group: Group, behaviour: Option[Behaviour]) {
|
case class GroundTruth(group: Group, behaviour: Option[Behaviour]) {
|
||||||
def simulate(cell: Cell, time: Time, prevTruth: Truth, result: Truth): Unit = {
|
def simulate(cell: Cell, time: Time, prevTruth: Truth, result: Truth): Unit = {
|
||||||
// don't need a truth, if the sensor uses another, but this should not happen
|
// don't need a truth, if the sensor uses another, but this should not happen
|
||||||
@@ -136,6 +142,6 @@ case class SensorCount(count: Int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: The Group is actually obsolete in the Tuple3 as Sensor and GroundTruth hold theirs (unless removed from their case class)
|
||||||
case class Configuration(cells: Map[Cell, Map[Group, List[(Group, Sensor, Option[GroundTruth])]]], sharedMemory: SharedMemory)
|
case class Configuration(cells: Map[Cell, Map[Group, List[(Group, Sensor, Option[GroundTruth])]]], sharedMemory: SharedMemory)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user