[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.components.{Parser, SimulationConfigParser, Output, Simulation}
import scim.datastruct.{Cell, FunctionArgs, SharedMemory, SimulationBehaviours, Time} import scim.datastruct.{Cell, FunctionArgs, SharedMemory, SimulationBehaviours, Time}
import scim.lib._ import scim.lib._
import scim.lib.simulation.SimulationBehaviour import scim.lib.simInterfaces.SimulationBehaviour
//package scim.components._ //package scim.components._
object Main { object Main {

View File

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

View File

@@ -1,8 +1,7 @@
package scim.components package scim.components
import scim.datastruct.{Behaviour, BehaviourVector, Cell, Configuration, FunctionArgs, GroundTruth, Group, Sensor, SensorCount, SensorResult, Time, Truth} import scim.datastruct.{Behaviour, BehaviourVector, Cell, Configuration, FunctionArgs, GroundTruth, Group, Sensor, SensorCount, SensorResult, Time, Truth}
import scim.lib.ConcurrentBroadcast.BroadcastObject import scim.lib.simInterfaces.SimulationBehaviour
import scim.lib.simulation.SimulationBehaviour
import scim.lib.debugUtil.{DebugType, debug, debugf} import scim.lib.debugUtil.{DebugType, debug, debugf}
class Simulation(config: Configuration) { 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 // 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))) 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 // 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) 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) val v: Vector[Option[(SimulationBehaviour, Option[FunctionArgs])]] = Vector.fill(time.duration)(None)
GroundTruth(group, Some(Behaviour(BehaviourVector(v)))).simulate(cell, time, prevTruth, resultTruth) 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 // simulate the sensor
sensor.simulate(time, resultTruth, resultSensors) sensor.simulate(time, resultTruth, resultSensors)
} }

View File

@@ -1,8 +1,8 @@
package scim.datastruct package scim.datastruct
import scim.lib.ConcurrentBroadcast.BroadcastObject import scim.lib.ConcurrentBroadcast._
import scim.lib.simulation._ import scim.lib.simInterfaces._
import scim.lib.configInterfaces._
import scala.collection.parallel.ForkJoinTaskSupport import scala.collection.parallel.ForkJoinTaskSupport
// configuration // 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]) { case class SimulationBehaviours(functions: Map[String, SimulationBehaviour]) {
def get(name: String): Option[SimulationBehaviour] = { def get(name: String): Option[SimulationBehaviour] = {
if(functions.contains(name)) Some(functions(name)) else None if(functions.contains(name)) Some(functions(name)) else None
} }
} }
case class SimulationConfig(duration: Int, runs: Int, tickfactor: Int = 1, case class SimulationConfig(duration: Int, runs: Int, tickfactor: Int = 1,
parCell: Int = 0, parCellThreads: Int = 5, parCell: Int = 0, parCellThreads: Int = 5,
parGroup: Int = 0, parGroupThreads: 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 groupThreadPool: ForkJoinTaskSupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(parGroupThreads))
val sensorThreadPool: ForkJoinTaskSupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(parSensorThreads)) 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 /* rough size estimation
Group(name: String, sensorParent: Option[String] = None) Group(name: String, sensorParent: Option[String] = None)
String: 2*x, String: 2*x 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 FunctionArgs(args: Map[String, Any])
case class BehaviourVector(function: Vector[Option[(SimulationBehaviour, Option[FunctionArgs])]], 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 // 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 // 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 = { 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
// as the parser should not create a ground truth in this case // 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 = { def simulate(time: Time, truth: Truth, results: Vector[SensorResult]): Unit = {
if(count.count == 0) return // allows for dummy sensors in dependency chains if(count.count == 0) return // allows for dummy sensors in dependency chains
if(parSensor != 0 && parSensor <= count.count) { 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 { package object parserUtil {
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 {
def parseDouble(number: Any): Option[Double] = { def parseDouble(number: Any): Option[Double] = {
number match { number match {
case t: java.lang.Number => Some(t.doubleValue()) case t: java.lang.Number => Some(t.doubleValue())