[ref] moved functionality of results and sim objects into traits

- added Interfaces.scala for traits
This commit is contained in:
2020-01-29 01:19:11 -06:00
parent 27c0ea4b35
commit d024ef84f8
6 changed files with 73 additions and 43 deletions

View File

@@ -3,7 +3,7 @@ package scim
import scim.components.{Parser, SimulationConfigParser, Output, Simulation}
import scim.datastruct.{Cell, FunctionArgs, SharedMemory, SimulationBehaviours, Time}
import scim.lib._
import scim.lib.simulation.SimulationBehaviour
import scim.lib.simInterfaces.SimulationBehaviour
//package scim.components._
object Main {

View File

@@ -4,10 +4,9 @@ import scim.datastruct.{Behaviour, BehaviourVector, Cell, Configuration, Functio
import scim.lib.ConcurrentBroadcast.BroadcastObject
import scim.lib.debugUtil.{DebugType, debugf}
import scim.lib.mapUtil._
import scim.lib.parser._
import scim.lib.simulation.SimulationBehaviour
import scim.lib.simInterfaces.SimulationBehaviour
import scim.lib.yml
import scim.lib.parserUtil._
import scala.collection.mutable
class Parser() {
@@ -55,11 +54,11 @@ class SimulationConfigParser(input: Map[String, Any], simulationBehaviours: Simu
val configurationMapping = sensorList.map(cell => cell._1 -> cellMapper(cell._1, cell._2.toMap)).toMap
// construct shared memory sensor
val sharedMemorySensor = Vector.tabulate(config.duration)(t => (Time(t, config.duration), sensorList.map(kv => kv._1 -> kv._2.map(kv2 => kv2._1 -> Vector.tabulate(kv2._2.count)(_ => SensorResult(new BroadcastObject()))).toMap).toMap))
val sharedMemorySensor = Vector.tabulate(config.duration)(t => (Time(t, config.duration), sensorList.map(kv => kv._1 -> kv._2.map(kv2 => kv2._1 -> Vector.tabulate(kv2._2.count)(_ => SensorResult())).toMap).toMap))
def truthHelper(cell: Cell, list: Map[Group, List[(Group, Sensor, Option[GroundTruth])]]): (Cell, Map[Group, Truth]) = {
val groupList: mutable.Map[Group, Truth] = mutable.Map()
list.foreach(kv => kv._2.foreach(e => groupList(e._1) = Truth(new BroadcastObject())))
list.foreach(kv => kv._2.foreach(e => groupList(e._1) = Truth()))
cell -> groupList.toMap
}
@@ -115,7 +114,7 @@ class SimulationConfigParser(input: Map[String, Any], simulationBehaviours: Simu
}
private def parseCells(cells: Vector[Any]): Map[Cell, SensorCount] = {
val parseCell: (Any) => (Cell, SensorCount) = (cell: Any) => cell match {
val parseCell: Any => (Cell, SensorCount) = (cell: Any) => cell match {
case cell: Vector[_] => val cellVector = cell.asInstanceOf[Vector[Int]]
(Cell(cellVector(0), cellVector(1)), SensorCount(cellVector(2)))
case cell: Map[_, _] => val cellMap = cell.asInstanceOf[Map[String, Int]]
@@ -244,16 +243,15 @@ class SimulationConfigParser(input: Map[String, Any], simulationBehaviours: Simu
val parseTruthHelper = (truthElement: Any) => {
truthElement match {
case truthObject: Vector[_] => {
val truth: Truth = Truth(new BroadcastObject())
println(truthElement)
val truth: Truth = Truth()
val start: Int = truthObject(0).asInstanceOf[Int]
// val end: Option[Int] = None // Not used
truth.set(parseDouble(truthObject(1)))
Map[Time, Truth](Time(start, config.duration) -> truth)
}
case truthObject: Map[_, _] => {
val truth: Truth = Truth(new BroadcastObject())
lazy val endTruth: Truth = Truth(new BroadcastObject())
val truth: Truth = Truth()
lazy val endTruth: Truth = Truth()
val truthObjectMap = truthObject.asInstanceOf[Map[String, Any]]
val timeline: Vector[Any] = truthObjectMap("timeline").asInstanceOf[Vector[Any]]
val timeLineVector: Vector[(Int, Option[Int])] = timeline.map(e => parseTimeLineElement(e))

View File

@@ -1,8 +1,7 @@
package scim.components
import scim.datastruct.{Behaviour, BehaviourVector, Cell, Configuration, FunctionArgs, GroundTruth, Group, Sensor, SensorCount, SensorResult, Time, Truth}
import scim.lib.ConcurrentBroadcast.BroadcastObject
import scim.lib.simulation.SimulationBehaviour
import scim.lib.simInterfaces.SimulationBehaviour
import scim.lib.debugUtil.{DebugType, debug, debugf}
class Simulation(config: Configuration) {
@@ -70,7 +69,7 @@ class Simulation(config: Configuration) {
// pass either subGroup truth, if truth is available for subGroup, or the sensor parents truth
val resTruth = if(subGroup.sensorParent.isEmpty) resultTruths(subGroup) else resultTruths(sharedMemory.groups(subGroup.parent.getOrElse(subGroup.name)))
// construct dummy result for sensors with count 0
val restSens = if(resultSensors.contains(subGroup)) resultSensors(subGroup) else Vector(SensorResult(new BroadcastObject()))
val restSens = if(resultSensors.contains(subGroup)) resultSensors(subGroup) else Vector(SensorResult())
simulate(time, cell, prevTruth, resTruth, restSens, element)
})
}
@@ -96,7 +95,7 @@ class Simulation(config: Configuration) {
val v: Vector[Option[(SimulationBehaviour, Option[FunctionArgs])]] = Vector.fill(time.duration)(None)
GroundTruth(group, Some(Behaviour(BehaviourVector(v)))).simulate(cell, time, prevTruth, resultTruth)
}
debugf(DebugType.DEBUG, "simulate: Time: %s | Cell: %s | Group: %s | Truth: %s", time.toString, cell.toString, group.toString, resultTruth.value.peak())
debugf(DebugType.DEBUG, "simulate: Time: %s | Cell: %s | Group: %s | Truth: %s", time.toString, cell.toString, group.toString, resultTruth.peak())
// simulate the sensor
sensor.simulate(time, resultTruth, resultSensors)
}

View File

@@ -1,8 +1,8 @@
package scim.datastruct
import scim.lib.ConcurrentBroadcast.BroadcastObject
import scim.lib.simulation._
import scim.lib.ConcurrentBroadcast._
import scim.lib.simInterfaces._
import scim.lib.configInterfaces._
import scala.collection.parallel.ForkJoinTaskSupport
// configuration
@@ -59,26 +59,14 @@ case class SharedMemory(sensor: Map[Time, Map[Cell, Map[Group, Vector[SensorResu
}
}
abstract class BroadcastHandler[A](broadcastObject: BroadcastObject[A]) {
def get: A = {
broadcastObject.watch()
}
def set(newValue: A): Unit = {
broadcastObject.broadcast(newValue)
}
def exists: Boolean = {
!broadcastObject.peak().isEmpty
}
def reset(): Unit = {
broadcastObject.broadcastReset()
}
}
case class SimulationBehaviours(functions: Map[String, SimulationBehaviour]) {
def get(name: String): Option[SimulationBehaviour] = {
if(functions.contains(name)) Some(functions(name)) else None
}
}
case class SimulationConfig(duration: Int, runs: Int, tickfactor: Int = 1,
parCell: Int = 0, parCellThreads: Int = 5,
parGroup: Int = 0, parGroupThreads: Int = 5,
@@ -87,7 +75,7 @@ case class SimulationConfig(duration: Int, runs: Int, tickfactor: Int = 1,
val groupThreadPool: ForkJoinTaskSupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(parGroupThreads))
val sensorThreadPool: ForkJoinTaskSupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(parSensorThreads))
}
case class SensorResult(result: BroadcastObject[(Group, Cell, Option[Double])]) extends BroadcastHandler(result)
case class SensorResult() extends Result[(Group, Cell, Option[Double])]
/* rough size estimation
Group(name: String, sensorParent: Option[String] = None)
String: 2*x, String: 2*x
@@ -119,7 +107,8 @@ case class Group(name: String, sensorParent: Option[String] = None){
}
}
}
case class Truth(value: BroadcastObject[Option[Double]]) extends BroadcastHandler(value)
case class Truth() extends Result[Option[Double]]
case class FunctionArgs(args: Map[String, Any])
case class BehaviourVector(function: Vector[Option[(SimulationBehaviour, Option[FunctionArgs])]],
@@ -142,7 +131,7 @@ 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]) extends SimObjectTruth {
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
// as the parser should not create a ground truth in this case
@@ -157,7 +146,7 @@ case class GroundTruth(group: Group, behaviour: Option[Behaviour]) {
}
}
case class Sensor(group: Group, cell: Cell, count: SensorCount, behaviour: Behaviour, parSensor: Int, sensorThreadPool: ForkJoinTaskSupport) {
case class Sensor(group: Group, cell: Cell, count: SensorCount, behaviour: Behaviour, parSensor: Int, sensorThreadPool: ForkJoinTaskSupport) extends SimObjectSensor {
def simulate(time: Time, truth: Truth, results: Vector[SensorResult]): Unit = {
if(count.count == 0) return // allows for dummy sensors in dependency chains
if(parSensor != 0 && parSensor <= count.count) {

View File

@@ -0,0 +1,50 @@
package scim.lib
import scim.datastruct.{Behaviour, Cell, Group, SensorCount, SensorResult, Time, Truth}
import scala.collection.parallel.ForkJoinTaskSupport
package object simInterfaces {
import scim.datastruct._
// maybe change to by-name parameters? have to check performance gain
type SimulationBehaviour = (Cell, Time, Option[Double], Option[FunctionArgs]) => Option[Double]
}
package object configInterfaces {
trait Result[A] {
val result = new scim.lib.ConcurrentBroadcast.BroadcastObject[A]()
def get: A = {
result.watch()
}
def set(newValue: A): Unit = {
result.broadcast(newValue)
}
def exists: Boolean = {
!result.peak().isEmpty
}
def reset(): Unit = {
result.broadcastReset()
}
def peak(): Option[A] = {
result.peak()
}
}
trait SimObjectSensor {
val cell: Cell
val count: SensorCount
val group: Group
val parSensor: Int
val sensorThreadPool: ForkJoinTaskSupport
val behaviour: Behaviour
def simulate(time: Time, truth: Truth, results: Vector[SensorResult]): Unit
}
trait SimObjectTruth {
val group: Group
val behaviour: Option[Behaviour]
def simulate(cell: Cell, time: Time, prevTruth: Truth, result:Truth): Unit
}
}

View File

@@ -322,13 +322,7 @@ package object yml {
}
}
package object simulation {
import scim.datastruct._
// maybe change to by-name parameters? have to check performance gain
type SimulationBehaviour = (Cell, Time, Option[Double], Option[FunctionArgs]) => Option[Double]
}
package object parser {
package object parserUtil {
def parseDouble(number: Any): Option[Double] = {
number match {
case t: java.lang.Number => Some(t.doubleValue())