All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unibo.scafi.lib.BlockG.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2016-2019, Roberto Casadei, Mirko Viroli, and contributors.
 * See the LICENSE file distributed with this work for additional information regarding copyright ownership.
*/

package it.unibo.scafi.lib

trait StdLibBlockG {
  self: StandardLibrary.Subcomponent =>

  // scalastyle:off method.name

  import Builtins._

  trait BlockG extends Gradients with FieldUtils with GenericUtils with StateManagement {
    self: FieldCalculusSyntax with StandardSensors =>

    /**
      * Version of G (Gradient-Cast) that takes a Gradient algorithm as input.
      * This is motivated by the desire of speeding G up by using
      * @param gradient The gradient algorithm to use -- notice that this encapsulates details about the gradient field (e.g., the sources)
      * @deprecated As it seems buggy: see {@link #G_along[V](Double,Metric,V,V=>V) G_along} method.
      */
    def Gg[V](gradient: Gradient, field: V, acc: V => V): V =
      G_along(gradient.run(), gradient.metric, field, acc)

    /**
      * Version of G (Gradient-Cast) that takes a potential field `g` as input
      * @param g potential field
      * @param metric metric to use for the "last step"
      * @param field value of the field for sources
      * @param acc aggregator
      * @tparam V type of the value to be accumulated
      * @return a field that locally provides the value of the gradient-cast (`field` at sources, and an accumulation value along the way)
      * @deprecated As it seems buggy.
      */
    def G_along[V](g: Double, metric: Metric, field: V, acc: V => V): V = {
      share(field) { case (_, neighbouringValue) =>
        mux(g==0.0){ field }{ excludingSelf.minHoodSelector[Double,V](nbr{g} + metric())(acc(neighbouringValue())).getOrElse(field) }
      }
    }

    def G[V](source: Boolean, field: V, acc: V => V, metric: () => Double): V =
      share((Double.MaxValue, field)) { case (_, neighbourOperator) =>
        mux(source) {
          (0.0, field)
        } {
          excludingSelf
            .minHoodSelector(neighbourOperator()._1 + metric())((neighbourOperator()._1 + metric(), acc(neighbourOperator()._2)))
            .getOrElse((Double.PositiveInfinity, field))
        }
      }._2

    /**
      * Curried version of [[G]]
      */
    def Gcurried[V](source: Boolean)(field: V)(acc: V => V)(metric: Metric = nbrRange): V =
      G(source, field, acc, metric)

    /**
      * A field of distance (i.e., a gradient) from a `source`, based on a given `metric`
      */
    def distanceTo(source: Boolean, metric: Metric = nbrRange): Double =
      Gcurried(source)(mux(source){0.0}{Double.PositiveInfinity})(_ + metric())()

    /**
      * Hop distance
      */
    def hopDistance(source: Boolean): Double = distanceTo(source, () =>1)

    /**
      * Broadcast information outward from a source field.
      * @param source The source of the broadcast
      * @param field Field denoting (1) at the source, the value to be broadcast; and (2) in other places, the default value of the broadcast field.
      * @param metric Metric that parameterises the gradient-based construction of the the propagation structure
      * @tparam V Type of the value to be broadcast
      * @return A broadcast field.
      */
    def broadcast[V](source: Boolean, field: V, metric: Metric = nbrRange): V =
      Gcurried(source)(field)(v => v)(metric)

    def broadcastAlongGradient[V](gf: Gradient, field: V): V = {
      val g = gf.run()
      excludingSelf.minHoodSelector(nbr { g })(nbr { field }).getOrElse(field)
    }

    /**
      * Distance between `source` to `target` based on `metric`
      */
    def distanceBetween(source: Boolean, target: Boolean, metric: Metric = nbrRange): Double =
      broadcast(source, distanceTo(target, metric), metric)

    /**
      * A channel from a `source` to a `target` with width `width`.
      * A channel is a boolean field which is true in correspondence of the device positioned
      *  along the minimum path from source to target.
      */
    def channel(source: Boolean, target: Boolean, width: Double): Boolean = {
      val ds = distanceTo(source)
      val dt = distanceTo(target)
      val db = distanceBetween(source, target)
      !((ds + dt).isInfinite && db.isInfinite) && ds + dt <= db + width
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy