diff --git a/build.sbt b/build.sbt index f435ab3f..973d0b43 100644 --- a/build.sbt +++ b/build.sbt @@ -83,4 +83,5 @@ def modelProject(projectName: String)(mainClassName: String): Project = { lazy val formin = modelProject("formin")("pl.edu.agh.formin.ForminMain") lazy val fortwist = modelProject("fortwist")("pl.edu.agh.fortwist.FortwistMain") lazy val torch = modelProject("torch")("pl.edu.agh.torch.TorchMain") -lazy val mock = modelProject("mock")("pl.edu.agh.mock.MockMain") \ No newline at end of file +lazy val mock = modelProject("mock")("pl.edu.agh.mock.MockMain") +lazy val wind = modelProject("wind")("pl.edu.agh.wind.WindMain") \ No newline at end of file diff --git a/formin/src/main/resources/reference.conf b/formin/src/main/resources/reference.conf index e98c6fce..ddd6cc8a 100644 --- a/formin/src/main/resources/reference.conf +++ b/formin/src/main/resources/reference.conf @@ -42,5 +42,7 @@ formin { iterationsNumber = 10000 isSupervisor = true shardingMod = 144 + crossBendFactor = 0 + straightBendFactor = 0 } } \ No newline at end of file diff --git a/formin/src/main/scala/pl/edu/agh/formin/config/ForminConfig.scala b/formin/src/main/scala/pl/edu/agh/formin/config/ForminConfig.scala index 41c3fa66..dc5961a7 100644 --- a/formin/src/main/scala/pl/edu/agh/formin/config/ForminConfig.scala +++ b/formin/src/main/scala/pl/edu/agh/formin/config/ForminConfig.scala @@ -39,5 +39,7 @@ final case class ForminConfig( workersRoot: Int, iterationsNumber: Long, isSupervisor: Boolean, - shardingMod: Int + shardingMod: Int, + crossBendFactor: Double, + straightBendFactor: Double ) extends XinukConfig diff --git a/formin/src/test/scala/pl.edu.agh.formin/GridTest.scala b/formin/src/test/scala/pl.edu.agh.formin/GridTest.scala index 9db0e9da..ef882fc2 100644 --- a/formin/src/test/scala/pl.edu.agh.formin/GridTest.scala +++ b/formin/src/test/scala/pl.edu.agh.formin/GridTest.scala @@ -28,7 +28,9 @@ class GridTest extends FlatSpecLike with Matchers with BeforeAndAfter { workersRoot = 1, iterationsNumber = 1000, isSupervisor = true, - 1 + 1, + crossBendFactor = 0, + straightBendFactor = 0 ) private var grid: Grid = _ @@ -59,8 +61,8 @@ class GridTest extends FlatSpecLike with Matchers with BeforeAndAfter { it should "propagate signal correctly for one foraminifera cell" in { grid.cells(2)(2) = ForaminiferaAccessible.unapply(EmptyCell.Instance).withForaminifera(config.foraminiferaStartEnergy, 0) - grid.cells(3)(2) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard, 3, 2) - grid.cells(3)(1) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard, 3, 1) + grid.cells(3)(2) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard(config), 3, 2) + grid.cells(3)(1) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard(config), 3, 1) grid.cells(2)(2).smell(0)(0).value shouldBe -1 grid.cells(2)(2).smell(0)(1).value shouldBe -1 @@ -73,8 +75,8 @@ class GridTest extends FlatSpecLike with Matchers with BeforeAndAfter { it should "propagate signal correctly for one algae cell" in { grid.cells(2)(2) = AlgaeAccessible.unapply(EmptyCell.Instance).withAlgae(0) - grid.cells(3)(2) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard, 3, 2) - grid.cells(3)(1) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard, 3, 1) + grid.cells(3)(2) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard(config), 3, 2) + grid.cells(3)(1) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard(config), 3, 1) grid.cells(2)(2).smell(0)(0).value shouldBe 1 grid.cells(2)(2).smell(0)(1).value shouldBe 1 @@ -88,8 +90,8 @@ class GridTest extends FlatSpecLike with Matchers with BeforeAndAfter { it should "propagate signal correctly between algae and foraminifera cells" in { grid.cells(2)(2) = AlgaeAccessible.unapply(EmptyCell.Instance).withAlgae(0) grid.cells(3)(2) = ForaminiferaAccessible.unapply(EmptyCell.Instance).withForaminifera(config.foraminiferaStartEnergy, 0) - val gridCellWithAlgaeAfterSignalPropagation = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard, 2, 2) - val gridCellWithForaminiferaAfterSignalPropagation = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard, 3, 2) + val gridCellWithAlgaeAfterSignalPropagation = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard(config), 2, 2) + val gridCellWithForaminiferaAfterSignalPropagation = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard(config), 3, 2) grid.cells(2)(2) = gridCellWithAlgaeAfterSignalPropagation grid.cells(3)(2) = gridCellWithForaminiferaAfterSignalPropagation @@ -110,7 +112,7 @@ class GridTest extends FlatSpecLike with Matchers with BeforeAndAfter { it should "not propagate signal on obstacle cell" in { grid.cells(3)(2) = ForaminiferaAccessible.unapply(EmptyCell.Instance).withForaminifera(config.foraminiferaStartEnergy, 0) - grid.cells(4)(2) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard, 4, 2) + grid.cells(4)(2) = grid.propagatedSignal(DefaultSmellPropagation.calculateSmellAddendsStandard(config), 4, 2) grid.cells(3)(2).smell(1)(1).value shouldBe -1 grid.cells(4)(2).smell(0)(1).value shouldBe 0 } diff --git a/formin/src/test/scala/pl.edu.agh.formin/MovesControllerTest.scala b/formin/src/test/scala/pl.edu.agh.formin/MovesControllerTest.scala index 7af2efcc..90d3186c 100644 --- a/formin/src/test/scala/pl.edu.agh.formin/MovesControllerTest.scala +++ b/formin/src/test/scala/pl.edu.agh.formin/MovesControllerTest.scala @@ -31,7 +31,9 @@ class MovesControllerTest extends FlatSpecLike with Matchers with BeforeAndAfter workersRoot = 1, iterationsNumber = 1000, isSupervisor = true, - shardingMod = 1 + shardingMod = 1, + crossBendFactor = 0, + straightBendFactor = 0 ) private var grid: Grid = _ diff --git a/formin/src/test/scala/pl.edu.agh.formin/ParallelTest.scala b/formin/src/test/scala/pl.edu.agh.formin/ParallelTest.scala index 93cf9386..4482a723 100644 --- a/formin/src/test/scala/pl.edu.agh.formin/ParallelTest.scala +++ b/formin/src/test/scala/pl.edu.agh.formin/ParallelTest.scala @@ -36,7 +36,9 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu workersRoot = 3, iterationsNumber = 3, isSupervisor = true, - shardingMod = 1 + shardingMod = 1, + crossBendFactor = 0, + straightBendFactor = 0 ) trait Fixture { @@ -47,7 +49,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Bottom), @@ -73,7 +75,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Bottom), @@ -95,7 +97,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Top), @@ -117,7 +119,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Top), @@ -139,7 +141,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Bottom), @@ -161,7 +163,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Bottom), @@ -193,7 +195,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Bottom), @@ -225,7 +227,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Bottom), @@ -257,7 +259,7 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(5), Vector(Neighbour(NeighbourPosition.Left), @@ -289,11 +291,11 @@ class ParallelTest extends FlatSpec with Matchers with Eventually with ScalaFutu val workerRegion = TestProbe("workerRegion") val worker1 = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) val worker2 = TestActorRef(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker1 ! WorkerActor.NeighboursInitialized(WorkerId(5), diff --git a/formin/src/test/scala/pl.edu.agh.formin/WorkerActorTest.scala b/formin/src/test/scala/pl.edu.agh.formin/WorkerActorTest.scala index 3bb00405..5e91f26e 100644 --- a/formin/src/test/scala/pl.edu.agh.formin/WorkerActorTest.scala +++ b/formin/src/test/scala/pl.edu.agh.formin/WorkerActorTest.scala @@ -33,7 +33,9 @@ class WorkerActorTest extends FlatSpecLike with Matchers with Eventually with Sc workersRoot = 2, iterationsNumber = 3, isSupervisor = true, - shardingMod = 1 + shardingMod = 1, + crossBendFactor = 0, + straightBendFactor = 0 ) trait Fixture { @@ -44,7 +46,7 @@ class WorkerActorTest extends FlatSpecLike with Matchers with Eventually with Sc val workerRegion = TestProbe("workerRegion") val worker = system.actorOf(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(2), Vector(Neighbour(NeighbourPosition.Bottom))) @@ -60,7 +62,7 @@ class WorkerActorTest extends FlatSpecLike with Matchers with Eventually with Sc val workerRegion = TestProbe("workerRegion") val worker = system.actorOf(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(2), Vector(Neighbour(NeighbourPosition.Bottom))) @@ -87,7 +89,7 @@ class WorkerActorTest extends FlatSpecLike with Matchers with Eventually with Sc val workerRegion = TestProbe("workerRegion") val worker = system.actorOf(WorkerActor.props[ForminConfig](workerRegion.ref, (bufferZone, config) => new ForminMovesController(bufferZone)(config), ForminConflictResolver, - DefaultSmellPropagation.calculateSmellAddendsStandard + DefaultSmellPropagation.calculateSmellAddendsStandard(config) )) worker ! WorkerActor.NeighboursInitialized(WorkerId(2), Vector()) diff --git a/fortwist/src/main/resources/reference.conf b/fortwist/src/main/resources/reference.conf index 13a81ad9..ed7f4512 100644 --- a/fortwist/src/main/resources/reference.conf +++ b/fortwist/src/main/resources/reference.conf @@ -41,5 +41,7 @@ fortwist { iterationsNumber = 10000 isSupervisor = true shardingMod = 144 + crossBendFactor = 0 + straightBendFactor = 0 } } \ No newline at end of file diff --git a/fortwist/src/main/scala/pl/edu/agh/fortwist/config/FortwistConfig.scala b/fortwist/src/main/scala/pl/edu/agh/fortwist/config/FortwistConfig.scala index e549c43b..4be68a26 100644 --- a/fortwist/src/main/scala/pl/edu/agh/fortwist/config/FortwistConfig.scala +++ b/fortwist/src/main/scala/pl/edu/agh/fortwist/config/FortwistConfig.scala @@ -39,5 +39,7 @@ final case class FortwistConfig( workersRoot: Int, iterationsNumber: Long, isSupervisor: Boolean, - shardingMod: Int + shardingMod: Int, + crossBendFactor: Double, + straightBendFactor: Double ) extends XinukConfig \ No newline at end of file diff --git a/mock/src/main/resources/reference.conf b/mock/src/main/resources/reference.conf index c18e222a..062cef2b 100644 --- a/mock/src/main/resources/reference.conf +++ b/mock/src/main/resources/reference.conf @@ -34,5 +34,8 @@ mock { iterationsNumber = 10000 mockInitialSignal = 1 + + crossBendFactor = 0 + straightBendFactor = 0 } } \ No newline at end of file diff --git a/mock/src/main/scala/pl.edu.agh.mock/config/MockConfig.scala b/mock/src/main/scala/pl.edu.agh.mock/config/MockConfig.scala index 8ca12a93..c44de4b0 100644 --- a/mock/src/main/scala/pl.edu.agh.mock/config/MockConfig.scala +++ b/mock/src/main/scala/pl.edu.agh.mock/config/MockConfig.scala @@ -16,5 +16,8 @@ final case class MockConfig( signalSpeedRatio: Int, iterationsNumber: Long, - mockInitialSignal: Signal + mockInitialSignal: Signal, + + crossBendFactor: Double, + straightBendFactor: Double ) extends XinukConfig \ No newline at end of file diff --git a/torch/src/main/resources/reference.conf b/torch/src/main/resources/reference.conf index 5c6441e7..db0a30a7 100644 --- a/torch/src/main/resources/reference.conf +++ b/torch/src/main/resources/reference.conf @@ -42,5 +42,7 @@ torch { iterationsNumber = 1000 isSupervisor = true shardingMod = 144 + crossBendFactor = 0 + straightBendFactor = 0 } } \ No newline at end of file diff --git a/torch/src/main/scala/pl.edu.agh.torch/config/TorchConfig.scala b/torch/src/main/scala/pl.edu.agh.torch/config/TorchConfig.scala index 1650184d..d1401bb8 100644 --- a/torch/src/main/scala/pl.edu.agh.torch/config/TorchConfig.scala +++ b/torch/src/main/scala/pl.edu.agh.torch/config/TorchConfig.scala @@ -4,7 +4,6 @@ import pl.edu.agh.xinuk.config.{GuiType, XinukConfig} import pl.edu.agh.xinuk.model.Signal final case class TorchConfig( - humanMaxSpeed: Int, fireSpeadingFrequency: Int, signalSpeedRatio: Int, @@ -23,5 +22,7 @@ final case class TorchConfig( workersRoot: Int, iterationsNumber: Long, isSupervisor: Boolean, - shardingMod: Int + shardingMod: Int, + crossBendFactor: Double, + straightBendFactor: Double ) extends XinukConfig \ No newline at end of file diff --git a/wind/src/main/resources/reference.conf b/wind/src/main/resources/reference.conf new file mode 100644 index 00000000..2516322e --- /dev/null +++ b/wind/src/main/resources/reference.conf @@ -0,0 +1,41 @@ +application { + name = wind +} + +clustering { + ip = "0.0.0.0" + port = 2551 + supervisor { + ip = "0.0.0.0" + port = 2551 + } + min-nr-of-members = 1 +} + +xinuk { + classes = [ + "pl.edu.agh.wind.model.WindSourceCell", + "pl.edu.agh.wind.simulation.WindMetrics", + ] +} + +wind { + config { + gridSize = 62 + guiCellSize = 4 + signalSuppressionFactor = 0.5 + signalAttenuationFactor = 1 + workersRoot = 1 + shardingMod = 144 + + guiType = basic + isSupervisor = true + signalSpeedRatio = 1 + iterationsNumber = 10000 + + crossBendFactor = 0.5 + straightBendFactor = 0.5 + + windSourceInitialSignal = 1 + } +} \ No newline at end of file diff --git a/wind/src/main/scala/pl/edu/agh/wind/WindMain.scala b/wind/src/main/scala/pl/edu/agh/wind/WindMain.scala new file mode 100644 index 00000000..c2916eb1 --- /dev/null +++ b/wind/src/main/scala/pl/edu/agh/wind/WindMain.scala @@ -0,0 +1,58 @@ +package pl.edu.agh.wind + +import java.awt.Color + +import com.typesafe.scalalogging.LazyLogging +import pl.edu.agh.wind.algorithm.WindMovesController +import pl.edu.agh.wind.model.WindSourceCell +import pl.edu.agh.wind.model.parallel.WindConflictResolver +import pl.edu.agh.xinuk.Simulation +import pl.edu.agh.xinuk.model.{DefaultSmellPropagation, Obstacle, SmellingCell} + +object WindMain extends LazyLogging { + private val configPrefix = "wind" + private val metricHeaders = Vector() + + def main(args: Array[String]): Unit = { + import pl.edu.agh.xinuk.config.ValueReaders._ + new Simulation( + configPrefix, + metricHeaders, + WindConflictResolver, + DefaultSmellPropagation.calculateSmellAddendsCurved + )( + new WindMovesController(_)(_), + { + case WindSourceCell(_) => Color.WHITE + case Obstacle => Color.GRAY + case cell: SmellingCell => colorSmell(cell: SmellingCell) + case _ => Color.BLACK + } + ).start() + } + + def colorSmell(cell: SmellingCell): Color = { + val smellValue = cell.smell.map(_.map(_.value).max).max.toFloat + + val brightness = Math.pow(smellValue, 0.1).toFloat + if (smellValue < 0.00001) { + val hue = 1f + val saturation = 1f + Color.getHSBColor(hue, saturation, brightness) + } else if (smellValue < 0.001) { + val hue = 0.65f + val saturation = 1f + Color.getHSBColor(hue, saturation, brightness) + } else if (smellValue < 0.1) { + val hue = 0.28f + val saturation = 1f + Color.getHSBColor(hue, saturation, brightness) + } else { + val hue = 0.11f + val saturation = 0.69f + Color.getHSBColor(hue, saturation, brightness) + } + } + +} + diff --git a/wind/src/main/scala/pl/edu/agh/wind/algorithm/WindMovesController.scala b/wind/src/main/scala/pl/edu/agh/wind/algorithm/WindMovesController.scala new file mode 100644 index 00000000..0b1a2e26 --- /dev/null +++ b/wind/src/main/scala/pl/edu/agh/wind/algorithm/WindMovesController.scala @@ -0,0 +1,49 @@ +package pl.edu.agh.wind.algorithm + +import pl.edu.agh.wind.config.WindConfig +import pl.edu.agh.wind.model.WindSourceCell +import pl.edu.agh.wind.simulation.WindMetrics +import pl.edu.agh.xinuk.algorithm.MovesController +import pl.edu.agh.xinuk.model.{Grid, Obstacle} + +import scala.collection.immutable.TreeSet + +final class WindMovesController(bufferZone: TreeSet[(Int, Int)])(implicit config: WindConfig) extends MovesController { + override def initialGrid: (Grid, WindMetrics) = { + val grid = Grid.empty(bufferZone) + val metrics = WindMetrics.empty() + + if (config.gridSize > 4) { + for (i <- 1 to config.gridSize - 2) { + grid.cells(1)(i) = Obstacle + grid.cells(i)(config.gridSize - 2) = Obstacle + + if (i < config.gridSize - 4) { + grid.cells(3)(i) = Obstacle + } + + if (i > 2) { + grid.cells(i)(config.gridSize - 4) = Obstacle + } + } + grid.cells(2)(1) = Obstacle + grid.cells(config.gridSize - 2)(config.gridSize - 3) = Obstacle + + grid.cells(2)(2) = WindSourceCell.create(config.windSourceInitialSignal) + } + + (grid, metrics) + } + + override def makeMoves(iteration: Long, grid: Grid): (Grid, WindMetrics) = { + val newGrid = Grid.empty(bufferZone) + + for { + x <- 0 until config.gridSize + y <- 0 until config.gridSize + } + newGrid.cells(x)(y) = grid.cells(x)(y) + + (newGrid, WindMetrics.empty()) + } +} diff --git a/wind/src/main/scala/pl/edu/agh/wind/config/WindConfig.scala b/wind/src/main/scala/pl/edu/agh/wind/config/WindConfig.scala new file mode 100644 index 00000000..9db859ce --- /dev/null +++ b/wind/src/main/scala/pl/edu/agh/wind/config/WindConfig.scala @@ -0,0 +1,23 @@ +package pl.edu.agh.wind.config + +import pl.edu.agh.xinuk.config.{GuiType, XinukConfig} +import pl.edu.agh.xinuk.model.Signal + +final case class WindConfig( + gridSize: Int, + guiCellSize: Int, + signalSuppressionFactor: Double, + signalAttenuationFactor: Double, + workersRoot: Int, + shardingMod: Int, + + guiType: GuiType, + isSupervisor: Boolean, + signalSpeedRatio: Int, + iterationsNumber: Long, + + crossBendFactor: Double, + straightBendFactor: Double, + + windSourceInitialSignal: Signal + ) extends XinukConfig \ No newline at end of file diff --git a/wind/src/main/scala/pl/edu/agh/wind/model/WindSourceCell.scala b/wind/src/main/scala/pl/edu/agh/wind/model/WindSourceCell.scala new file mode 100644 index 00000000..6d337f33 --- /dev/null +++ b/wind/src/main/scala/pl/edu/agh/wind/model/WindSourceCell.scala @@ -0,0 +1,14 @@ +package pl.edu.agh.wind.model + +import pl.edu.agh.xinuk.model.Cell.SmellArray +import pl.edu.agh.xinuk.model.{Cell, Signal, SmellingCell} + +final case class WindSourceCell(smell: SmellArray) extends SmellingCell { + override type Self = WindSourceCell + + override def withSmell(smell: SmellArray): WindSourceCell = copy(smell = smell) +} + +object WindSourceCell { + def create(initialSignal: Signal): WindSourceCell = WindSourceCell(Array.fill(Cell.Size, Cell.Size)(initialSignal)) +} \ No newline at end of file diff --git a/wind/src/main/scala/pl/edu/agh/wind/model/parallel/WindConflictResolver.scala b/wind/src/main/scala/pl/edu/agh/wind/model/parallel/WindConflictResolver.scala new file mode 100644 index 00000000..9ee680e9 --- /dev/null +++ b/wind/src/main/scala/pl/edu/agh/wind/model/parallel/WindConflictResolver.scala @@ -0,0 +1,34 @@ +package pl.edu.agh.wind.model.parallel + +import pl.edu.agh.wind.config.WindConfig +import pl.edu.agh.wind.model.WindSourceCell +import pl.edu.agh.wind.simulation.WindMetrics +import pl.edu.agh.xinuk.model.parallel.ConflictResolver +import pl.edu.agh.xinuk.model._ + +object WindConflictResolver extends ConflictResolver[WindConfig] { + + import Cell._ + + override def resolveConflict(current: GridPart, incoming: SmellingCell)(implicit config: WindConfig): (GridPart, WindMetrics) = { + (current, incoming) match { + + case (Obstacle, _) => + (Obstacle, WindMetrics.empty()) + + case (EmptyCell(currentSmell), EmptyCell(incomingSmell)) => + (EmptyCell(currentSmell + incomingSmell), WindMetrics.empty()) + + case (WindSourceCell(currentSmell), EmptyCell(incomingSmell)) => + (WindSourceCell(currentSmell + incomingSmell), WindMetrics.empty()) + + case (EmptyCell(currentSmell), WindSourceCell(incomingSmell)) => + (WindSourceCell(currentSmell + incomingSmell), WindMetrics.empty()) + + case (WindSourceCell(currentSmell), WindSourceCell(incomingSmell)) => + (WindSourceCell(currentSmell + incomingSmell), WindMetrics.empty()) + + case (x, y) => throw new UnsupportedOperationException(s"Unresolved conflict: $x with $y") + } + } +} diff --git a/wind/src/main/scala/pl/edu/agh/wind/simulation/WindMetrics.scala b/wind/src/main/scala/pl/edu/agh/wind/simulation/WindMetrics.scala new file mode 100644 index 00000000..af08ea21 --- /dev/null +++ b/wind/src/main/scala/pl/edu/agh/wind/simulation/WindMetrics.scala @@ -0,0 +1,21 @@ +package pl.edu.agh.wind.simulation + +import pl.edu.agh.xinuk.simulation.Metrics + +final case class WindMetrics() extends Metrics { + override def log: String = { + s"" + } + + override def series: Vector[(String, Double)] = Vector() + + override def +(other: Metrics): WindMetrics = { + this + } +} + +object WindMetrics { + private val EMPTY = WindMetrics() + + def empty(): WindMetrics = EMPTY +} diff --git a/xinuk-core/src/main/scala/pl/edu/agh/xinuk/Simulation.scala b/xinuk-core/src/main/scala/pl/edu/agh/xinuk/Simulation.scala index d271f75c..c5b0ac52 100644 --- a/xinuk-core/src/main/scala/pl/edu/agh/xinuk/Simulation.scala +++ b/xinuk-core/src/main/scala/pl/edu/agh/xinuk/Simulation.scala @@ -23,7 +23,7 @@ class Simulation[ConfigType <: XinukConfig : ValueReader]( configPrefix: String, metricHeaders: Vector[String], conflictResolver: ConflictResolver[ConfigType], - smellPropagationFunction: (CellArray, Int, Int) => Vector[Option[Signal]], + smellPropagationFunction: XinukConfig => (CellArray, Int, Int) => Vector[Option[Signal]], emptyCellFactory: => SmellingCell = EmptyCell.Instance)( movesControllerFactory: (TreeSet[(Int, Int)], ConfigType) => MovesController, cellToColor: PartialFunction[GridPart, Color] = PartialFunction.empty @@ -40,12 +40,12 @@ class Simulation[ConfigType <: XinukConfig : ValueReader]( private def logHeader: String = s"worker:${metricHeaders.mkString(";")}" implicit val config: ConfigType = { - val forminConfig = rawConfig.getConfig(configPrefix) - logger.info(WorkerActor.MetricsMarker, forminConfig.root().render(ConfigRenderOptions.concise())) + val conf = rawConfig.getConfig(configPrefix) + logger.info(WorkerActor.MetricsMarker, conf.root().render(ConfigRenderOptions.concise())) logger.info(WorkerActor.MetricsMarker, logHeader) import net.ceedubs.ficus.Ficus._ - Try(forminConfig.as[ConfigType]("config")) match { + Try(conf.as[ConfigType]("config")) match { case Success(parsedConfig) => parsedConfig case Failure(parsingError) => @@ -59,7 +59,13 @@ class Simulation[ConfigType <: XinukConfig : ValueReader]( private val workerRegionRef: ActorRef = ClusterSharding(system).start( typeName = WorkerActor.Name, - entityProps = WorkerActor.props[ConfigType](workerRegionRef, movesControllerFactory, conflictResolver, smellPropagationFunction, emptyCellFactory), + entityProps = WorkerActor.props[ConfigType]( + workerRegionRef, + movesControllerFactory, + conflictResolver, + smellPropagationFunction(config.asInstanceOf[XinukConfig]), + emptyCellFactory + ), settings = ClusterShardingSettings(system), extractShardId = WorkerActor.extractShardId, extractEntityId = WorkerActor.extractEntityId diff --git a/xinuk-core/src/main/scala/pl/edu/agh/xinuk/config/XinukConfig.scala b/xinuk-core/src/main/scala/pl/edu/agh/xinuk/config/XinukConfig.scala index 303e3344..05628862 100644 --- a/xinuk-core/src/main/scala/pl/edu/agh/xinuk/config/XinukConfig.scala +++ b/xinuk-core/src/main/scala/pl/edu/agh/xinuk/config/XinukConfig.scala @@ -14,6 +14,9 @@ trait XinukConfig { def isSupervisor: Boolean def signalSpeedRatio: Int def iterationsNumber: Long + + def crossBendFactor: Double + def straightBendFactor: Double } sealed trait GuiType extends NamedEnum diff --git a/xinuk-core/src/main/scala/pl/edu/agh/xinuk/model/DefaultSmellPropagation.scala b/xinuk-core/src/main/scala/pl/edu/agh/xinuk/model/DefaultSmellPropagation.scala index 4d42a1a5..1e700287 100644 --- a/xinuk-core/src/main/scala/pl/edu/agh/xinuk/model/DefaultSmellPropagation.scala +++ b/xinuk-core/src/main/scala/pl/edu/agh/xinuk/model/DefaultSmellPropagation.scala @@ -1,44 +1,109 @@ package pl.edu.agh.xinuk.model +import pl.edu.agh.xinuk.config.XinukConfig import pl.edu.agh.xinuk.model.Cell.SmellArray import pl.edu.agh.xinuk.model.Grid.{CellArray, SubcellCoordinates} object DefaultSmellPropagation { - def calculateSmellAddendsStandard(cells: CellArray, x: Int, y: Int): Vector[Option[Signal]] = { - @inline def destinationCellSignal(i: Int, j: Int): Option[SmellArray] = { - cells.lift(x + i - 1).flatMap(_.lift(y + j - 1).map(_.smell)) - } + def calculateSmellAddendsStandard(config: XinukConfig): (CellArray, Int, Int) => Vector[Option[Signal]] = { + def calculateSmellAddendsStandard(cells: CellArray, x: Int, y: Int): Vector[Option[Signal]] = { + @inline def destinationCellSignal(i: Int, j: Int): Option[SmellArray] = { + cells.lift(x + i - 1).flatMap(_.lift(y + j - 1).map(_.smell)) + } - SubcellCoordinates.map { - case (i, j) if i == 1 || j == 1 => - destinationCellSignal(i, j).map(signal => - signal(i)(j) + signal(i + j - 1)(i + j - 1) + signal(i - j + 1)(j - i + 1) - ) - case (i, j) => - destinationCellSignal(i, j).map(_.apply(i)(j)) + SubcellCoordinates.map { + case (i, j) if i == 1 || j == 1 => + destinationCellSignal(i, j).map(signal => + signal(i)(j) + signal(i + j - 1)(i + j - 1) + signal(i - j + 1)(j - i + 1) + ) + case (i, j) => + destinationCellSignal(i, j).map(_.apply(i)(j)) + } } + calculateSmellAddendsStandard } - def calculateSmellAddendsCircular(cells: CellArray, x: Int, y: Int): Vector[Option[Signal]] = { - def sideToSide = 1.0 / 3 - def sideToCorner = 1.0 / Math.sqrt(10) - def cornerToSide = 1.0 / Math.sqrt(13) - def cornerToCorner = 1.0 / (3 * Math.sqrt(2)) + def calculateSmellAddendsCircular(config: XinukConfig): (CellArray, Int, Int) => Vector[Option[Signal]] = { + def calculateSmellAddendsCircular(cells: CellArray, x: Int, y: Int): Vector[Option[Signal]] = { + def sideToSide = 1.0 / 3 + + def sideToCorner = 1.0 / Math.sqrt(10) + + def cornerToSide = 1.0 / Math.sqrt(13) + + def cornerToCorner = 1.0 / (3 * Math.sqrt(2)) - @inline def destinationCellSignal(i: Int, j: Int): Option[SmellArray] = { - cells.lift(x + i - 1).flatMap(_.lift(y + j - 1).map(_.smell)) + @inline def destinationCellSignal(i: Int, j: Int): Option[SmellArray] = { + cells.lift(x + i - 1).flatMap(_.lift(y + j - 1).map(_.smell)) + } + + SubcellCoordinates.map { + case (i, j) if i == 1 || j == 1 => + destinationCellSignal(i, j).map(signal => + signal(i)(j) * sideToSide + (signal(i + j - 1)(i + j - 1) + signal(i - j + 1)(j - i + 1)) * cornerToSide + ) + case (i, j) => + destinationCellSignal(i, j).map(signal => + signal(i)(j) * cornerToCorner + (signal(i)(1) + signal(1)(j)) * sideToCorner + ) + } } + calculateSmellAddendsCircular + } + + def calculateSmellAddendsCurved(config: XinukConfig): (CellArray, Int, Int) => Vector[Option[Signal]] = { + def calculateSmellAddendsCurved(cells: CellArray, x: Int, y: Int): Vector[Option[Signal]] = { + @inline def destinationCellSignal(i: Int, j: Int): Option[SmellArray] = { + cells.lift(x + i - 1).flatMap(_.lift(y + j - 1).map(_.smell)) + } + + val crossWeight: Double = config.crossBendFactor + val straightWeight: Double = config.straightBendFactor - SubcellCoordinates.map { - case (i, j) if i == 1 || j == 1 => - destinationCellSignal(i, j).map(signal => - signal(i)(j) * sideToSide + (signal(i + j - 1)(i + j - 1) + signal(i - j + 1)(j - i + 1)) * cornerToSide - ) - case (i, j) => - destinationCellSignal(i, j).map(signal => - signal(i)(j) * cornerToCorner + (signal(i)(1) + signal(1)(j)) * sideToCorner - ) + SubcellCoordinates.map { + case (i, j) if i == 1 || j == 1 => + destinationCellSignal(i, j).map(signal => + signal(i)(j) + signal(i + j - 1)(i + j - 1) + signal(i - j + 1)(j - i + 1) + ) + case (i, j) if i == 0 && j == 0 => + destinationCellSignal(i, j).map(signal => { + var signalSum = signal(0)(0) + if (cells(x - 1)(y) == Obstacle) + signalSum += (signal(0)(1) * straightWeight + signal(0)(2) * crossWeight) + if (cells(x)(y - 1) == Obstacle) + signalSum += (signal(1)(0) * straightWeight + signal(2)(0) * crossWeight) + signalSum + }) + case (i, j) if i == 2 && j == 0 => + destinationCellSignal(i, j).map(signal => { + var signalSum = signal(2)(0) + if (cells(x + 1)(y) == Obstacle) + signalSum += (signal(2)(1) * straightWeight + signal(2)(2) * crossWeight) + if (cells(x)(y - 1) == Obstacle) + signalSum += (signal(0)(0) * straightWeight + signal(1)(0) * crossWeight) + signalSum + }) + case (i, j) if i == 0 && j == 2 => + destinationCellSignal(i, j).map(signal => { + var signalSum = signal(0)(2) + if (cells(x - 1)(y) == Obstacle) + signalSum += (signal(0)(0) * straightWeight + signal(0)(1) * crossWeight) + if (cells(x)(y + 1) == Obstacle) + signalSum += (signal(1)(2) * straightWeight + signal(2)(2) * crossWeight) + signalSum + }) + case (i, j) if i == 2 && j == 2 => + destinationCellSignal(i, j).map(signal => { + var signalSum = signal(2)(2) + if (cells(x + 1)(y) == Obstacle) + signalSum += (signal(2)(0) * straightWeight + signal(2)(1) * crossWeight) + if (cells(x)(y + 1) == Obstacle) + signalSum += (signal(0)(2) * straightWeight + signal(1)(2) * crossWeight) + signalSum + }) + } } + calculateSmellAddendsCurved } }