From d024ef84f8af6fd028acad67ab9ddc3933b6fac1 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 29 Jan 2020 01:19:11 -0600 Subject: [PATCH] [ref] moved functionality of results and sim objects into traits - added Interfaces.scala for traits --- src/main/scala/scim/Main.scala | 2 +- src/main/scala/scim/components/Parser.scala | 18 +++---- .../scala/scim/components/Simulation.scala | 7 ++- .../scala/scim/datastruct/Configuration.scala | 31 ++++-------- src/main/scala/scim/lib/Interfaces.scala | 50 +++++++++++++++++++ src/main/scala/scim/lib/Library.scala | 8 +-- 6 files changed, 73 insertions(+), 43 deletions(-) create mode 100644 src/main/scala/scim/lib/Interfaces.scala diff --git a/src/main/scala/scim/Main.scala b/src/main/scala/scim/Main.scala index 4ea1df0..03b0751 100644 --- a/src/main/scala/scim/Main.scala +++ b/src/main/scala/scim/Main.scala @@ -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 { diff --git a/src/main/scala/scim/components/Parser.scala b/src/main/scala/scim/components/Parser.scala index 0a6ab6a..9ff70f8 100644 --- a/src/main/scala/scim/components/Parser.scala +++ b/src/main/scala/scim/components/Parser.scala @@ -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)) diff --git a/src/main/scala/scim/components/Simulation.scala b/src/main/scala/scim/components/Simulation.scala index 78bf136..ae293cd 100644 --- a/src/main/scala/scim/components/Simulation.scala +++ b/src/main/scala/scim/components/Simulation.scala @@ -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) } diff --git a/src/main/scala/scim/datastruct/Configuration.scala b/src/main/scala/scim/datastruct/Configuration.scala index 91255c0..8d8f852 100644 --- a/src/main/scala/scim/datastruct/Configuration.scala +++ b/src/main/scala/scim/datastruct/Configuration.scala @@ -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) { diff --git a/src/main/scala/scim/lib/Interfaces.scala b/src/main/scala/scim/lib/Interfaces.scala new file mode 100644 index 0000000..27163b2 --- /dev/null +++ b/src/main/scala/scim/lib/Interfaces.scala @@ -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 + } +} \ No newline at end of file diff --git a/src/main/scala/scim/lib/Library.scala b/src/main/scala/scim/lib/Library.scala index da968d3..091b349 100644 --- a/src/main/scala/scim/lib/Library.scala +++ b/src/main/scala/scim/lib/Library.scala @@ -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())