
protelis.coord.spreading.pt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of protelis-lang Show documentation
Show all versions of protelis-lang Show documentation
Essential libraries for the Protelis language
module protelis:coord:spreading
import org.apache.commons.math3.util.FastMath.floor
import protelis:lang:utils
import protelis:state:time
/*
* Add v to the field of distances from the current device.
*
* @param v num, distance to add
* @return num, field of distances from the current device
*/
public def addRange(v) {
addRangeWithMetric(v, nbrRange)
}
/*
* Add of 1 the field of distances of the current device's neighbors.
*
* @return num, field of distances from the current device
*/
public def addRangeHop() {
addRangeWithMetric(1, nbrRangeHop)
}
/*
* Add v to the field of distances from the current device.
*
* @param v num, distance to add
* @param metric () -> num, estimate distance from other devices
* @param speed num, communication speed
* @return num, field of distances from the current device
*/
public def addRangeWithLag(v, metric, speed) {
addRangeWithMetric(v, () -> { nbrRangeLag(metric, nbrLag, speed) })
}
/*
* Add v to the field of distances from the current device.
*
* @param v num, distance to add
* @param metric () -> num, estimate distance from other devices
* @return num, field of distances from the current device
*/
public def addRangeWithMetric(v, metric) {
v + metric.apply()
}
/**
* Constrain the spreading of broadcast function only within a region.
*
* @param region bool, whether the function is spreaded or not
* @param null T, default value where f is not spreaded
* @param source bool, whether the current device is a source
* @param T, value what to broadcast
* @return T, broadcast inside the region, return null otherwise
*/
public def boundBroadcast(region, null, source, value) {
boundSpreading(region, () -> { broadcast(source, value) }, null)
}
/**
* Constrain the spreading of G function only within a region.
* @param region bool, whether the function is spreaded or not
* @param null T, default value where f is not spreaded
* @param source bool, whether the current device is a source
* @param initial T, initial value of the computation
* @param metric () -> num, estimate distance from other devices
* @param accumulate (T) -> T, how to manage the value
* @return T, accumulated value
*/
public def boundG(region, null, source, initial, metric, accumulate) {
boundSpreading(region, () -> {
G(source, initial, metric, accumulate)
}, null)
}
/*
* Distance from the current to the closest source.
*
* @param region bool, where to compute distanceTo
* @param source bool, whether the device is a source
* @return num, field of minimum distances to the closest source
*/
public def boundDistanceTo(region, source) {
boundSpreading(region, () -> { distanceTo(source) }, Infinity)
}
/**
* Constrain the spreading of f only across a region.
*
* @param region bool, whether the function is spreaded or not
* @param f () -> T, function to be spreaded
* @param null T, default value where f is not spreaded
* @return T, apply f inside the region, null outside
*/
public def boundSpreading(region, f, null) {
if (region) {
f.apply()
} else {
null
}
}
/**
* Constrain the spreading of f only within devices close to the source.
*
* @param range () -> bool, how to determine the range
* @param f () -> T, function to be spreaded
* @param null T, default value where f is not spreaded
* @return T, apply f inside the region, null outside
*/
public def boundSpreadingWithRange(range, f, null) {
boundSpreading(range.apply(), f, null);
}
/*
* Broadcast value across a spanning tree starting from the source.
*
* @param source bool, whether the current device is a source
* @param value T, what to broadcast
* @return T, broadcasted value
*/
public def broadcast(source, value) {
broadcastWithMetric(source, value, nbrRange)
}
/*
* Broadcast value across a spanning tree starting from the source.
*
* @param source bool, whether the current device is a source
* @param value T, what to broadcast
* @param metric () -> num, estimate distance from other devices
* @return T, broadcasted value
*/
public def broadcastWithMetric(source, value, metric) {
G(source, value, metric, identity)
}
/**
* Dynamically computes distributed routes between regions of a network, and
* dynamically adapts to shape and changes of the network topology. Examples
* of its use include long-range reliable communications, or advanced crowd
* steering applications in pervasive computing. The �channel� is a Boolean
* field that is true for devices near the shortest route from a given
* (distributed) source to a (distributed) destination.
*
* @param source bool, whether the device is a source
* @param dest bool, whether the device is a destination
* @param obstacle bool, whether the device is an obstacle
* @param thr num, threshold for Double comparison (e.g. 0.01)
* @param width num, how much to dilate the channel
* @return bool, true if the device is on the shortest path, false otherwise
*/
public def channel(source, dest, obstacle, thr, width) {
boundSpreading(!obstacle, () -> {
let d = distanceBetween(source, dest);
if (d == Infinity) { false }
else {
distanceTo(distanceTo(source) + distanceTo(dest) <= d + thr) <= width
}
}, false)
}
/**
* Channel pattern.
*
* @param source bool, whether the device is a source
* @param dest bool, whether the device is a destination
* @param obstacle bool, whether the device is an obstacle
* @param width num, how much to dilate the channel
* @return bool, true if the device is on the shortest path, false otherwise
*/
public def channel2(source, destination, obstacle, width) {
boundSpreading(!obstacle, () -> {
distanceTo(shortestPath(source, destination)) <= width
}, false)
}
/**
* @param source bool, whether the device is a source
* @param range num, range
* @return bool, true if the device is closer than range to the source
*/
public def closerThan(source, range) {
distanceToWithMetric(source, nbrRange) < range
}
/**
* @param source bool, whether the device is a source
* @param metric () -> num, how to estimate the distance
* @param range num, range
* @return bool, true if the device is closer than range to the source
*/
public def closerThanWithMetric(source, metric, range) {
distanceToWithMetric(source, metric) < range
}
/**
* Self-healing gradcast algorithm that reconfigures in O(diameter) time.
* Requires euclidean metric. The CRF-Gradient algorithm handles this problem
* by splitting the calculation into constraint and restoring force behaviors.
* When constraint is dominant, the value of a device gx(t) stays fixed or
* decreases, set by the triangle inequality from its neighbors� values. When
* restoring force is dominant, gx(t) rises at a fixed velocity v0.
*
* @param source bool, whether the device is a source
* @param metric () -> num, how to estimate distances without lag
* @param maxHop num, communication max range
* @return num, minimum distance from the source
*/
public def crfGradient(source, metric, maxHop) {
rep (potential <- [Infinity, 0]) {
mux (source) {
[0, 0]
} else {
let d = nbr(potential).get(0);
let dt = self.getDeltaTime();
mux (anyHood(addRangeWithLag(d, metric, potential.get(1)) < potential.get(0))) {
minHood([d + metric.apply(), 0])
} else {
let v0 = if (dt == 0) { maxHop } else { maxHop / (dt * 12) };
[potential.get(0) + v0 * dt, v0]
}
}
}.get(0)
}
/**
* Dilate a spatial region.
*
* @param region bool, whether the device is inside the region
* @param width num, how much to dilate
* @return bool, dilated region
*/
public def dilate(region, width) {
dilateWithMetric(region, nbrRange, width)
}
/**
* Dilate a spatial region.
*
* @param region bool, whether the device is inside the region
* @param metric () -> num, how to estimate the distance between devices
* @param width num, how much to dilate
* @return bool, dilated region
*/
public def dilateWithMetric(region, metric, width) {
distanceToWithMetric(region, metric) < width
}
/**
* Forecast obstacles along a path to the source.
*
* @param source bool, whether the device is a source
* @param obstacle bool, whether the device is an obstacle
* @return bool, true if the device encounter an obstacle within the shortest
* path towards the closest source, false otherwise
*/
public def directProjection(source, obstacle) {
directProjectionWithMetric(source, obstacle, nbrRange)
}
/**
* Forecast obstacles along a path to the source.
*
* @param source bool, whether the device is a source
* @param obstacle bool, whether the device is an obstacle
* @param metric () -> num, how to estimate neighbors distances
* @return bool, true if the device encounter an obstacle within the shortest
* path towards the closest source, false otherwise
*/
public def directProjectionWithMetric(source, obstacle, metric) {
G(source, obstacle, metric, (v) -> { obstacle || Gnull(v, false) })
}
/**
* Smallest distance between source and destination devices.
*
* @param source bool, whether the current device is a source
* @param dest bool, whether the current device is a destination
* @return num, smallest distance between source and destination devices
*/
public def distanceBetween(source, dest) {
distanceBetweenWithMetric(source, dest, nbrRange)
}
/**
* Smallest distance between source and destination devices.
*
* @param source bool, whether the current device is a source
* @param dest bool, whether the current device is a destination
* @param metric () -> num, estimate distance from other devices
* @return num, smallest distance between source and destination devices
*/
public def distanceBetweenWithMetric(source, dest, metric) {
G(source, distanceToWithMetric(dest, metric), metric, identity)
}
/*
* Distance from the current to the closest source.
*
* @param source bool, whether the current device is a source
* @return num, distance to the closest source
*/
public def distanceTo(source) {
distanceToWithMetric(source, nbrRange)
}
/*
* Distance from the current to the closest source.
*
* @param source bool, whether the device is a source
* @param metric () -> num, estimate distance from other devices
* @return num, field of minimum distances to the closest source
*/
public def distanceToWithMetric(source, metric) {
G(source, 0, metric, (v) -> { v + metric.apply() })
}
/**
* Used by flexGradient
*/
def slope(d, minD, metric) {
let nrange = metric.apply();
if (nrange > 0) {
let ndv = nbr(d);
let m = max(minD, maxHood(nrange));
maxHood([(d - ndv)/m, ndv, m])
} else { [0, d, 0] }
}
/**
* Flex-Gradient.
*
* @param source bool, whether the device is a source
* @param epsilon num, tolerance
* @param rate num, communication rate
* @param range num, communication range
* @param distortion num, distortion
* @param metric () -> num, estimate distance from other devices
*/
public def flexGradient(source, epsilon, rate, range, distortion, metric) {
rep (d <- Infinity) {
mux (source) {
0
} else {
let minD = range * distortion;
let slopeInfo = slope(d, minD, metric);
let maxSlope = slopeInfo.get(0);
let msd = slopeInfo.get(1);
let msr = slopeInfo.get(2);
let ct = minHood(nbr(d) + max(minD, maxHood(metric.apply())));
mux ((d > range && d > ct * 2) || cyclicTimer((d + self.getDeltaTime()) * rate)) {
ct
} else {
mux (maxSlope > (1 + epsilon)) {
msd + msr * (1 + epsilon)
} else {
mux (maxSlope < (1 - epsilon)) {
msd + msr * (1 - epsilon)
} else {
d
}
}
}
}
}
}
/*
* Propagate values across a spanning tree starting from the closest source.
*
* @param source bool, whether the current device is a source
* @param initial T, initial value of the computation
* @param metric () -> num, estimate distance from other devices
* @param accumulate (T) -> T, how to accumulate the value
* @return T, accumulated value
*/
public def G(source, initial, metric, accumulate) {
rep (distanceValue <- [Infinity, initial]) {
mux (source) {
// If the device is a source then G return a 0 potential
// and the initial value
[0, initial]
} else {
// The other device potentials are requested
let ndv = nbr(distanceValue);
// G returns the value related to the minimum potential
// TODO do we need a default?
minHood([
// potential estimation
ndv.get(0) + metric.apply(),
// values estimation
accumulate.apply(ndv.get(1))
])
}
}.get(1) // return the accumulated value
}
/**
* Wrapper for G error.
* For example: G(aBool, aBool, aMetric, (v) -> { Gnull(v, false) ... }
* assure that G is not broken in case minHood([..., ...]) returns Infinity.
*
* @param v T, value to be checked
* @param default T, default value to avoid to broke G
* @return T, v or default
*/
public def Gnull(v, default) {
mux (v == Infinity) {
default
} else {
v
}
}
/**
* Gradcast.
*
* @param source bool, whether the device is a source
* @param gradient num, gradient to follow
* @param local T, local value
* @param accumulate (T) -> T, how to accumulate local values
* @return T, accumulated value
*/
public def gradcast(source, gradient, local, accumulate) {
rep (value <- local) {
mux (source) {
local
} else {
minHood([nbr(gradient.apply()), accumulate.apply(nbr(value))]).get(1)
}
}
}
/**
* Determine the smallest distance from the current device to the source.
*
* @param source bool, whether the device is a source
* @param init num, distance initial value
* @param metric () -> num, estimate distance from other devices
* @param range num, communication range
* @return num, minimum distance from the closest source
*/
public def gradient(source, init, metric, range) {
rep (distance <- [Infinity, 0]) {
mux (source) {
[init, 0]
} else {
let d = distance.get(0);
let v = distance.get(1);
mux (anyHood(addRangeWithLag(nbr(distance).get(0), metric, v) <= d)) {
let ndv = nbr(distance);
minHood([ndv.get(0) + metric.apply(), 0])
} else {
let v0 = range / 2;
[d + v0 * self.getDeltaTime(), v0]
}
}
}.get(0)
}
/**
* Count the number of neighbors.
*
* @return num, number of neighbors
*/
public def neighborhood() {
sumHood(nbr(1))
}
/**
* Communication latency.
*
* @return num, communication latencies between this device and its
* neighbors
*/
public def nbrLag() {
self.nbrLag()
}
/*
* Estimate the distance of the current device.
*
* @return num, field of distances from the current device
*/
public def nbrRange() {
self.nbrRange()
}
/*
* Estimate the distance from the current device.
*
* @return num, field of 1s for each neighbor
*/
public def nbrRangeHop() {
1
}
/*
* Estimate the distance of the current device.
*
* @param metric () -> num, how to estimate distances
* @param lagmetric () -> num, how to estimate latencies
* @param speed num, communication speed
* @return num, field of distances from the current device
*/
public def nbrRangeLag(metric, lagMetric, speed) {
metric.apply() + (lagMetric.apply() + self.getDeltaTime()) * speed
}
/**
* Shortest path according to a potential.
*
* @param source bool, whether the device is a source
* @param potential num, potential
* @return bool, true if the device is in the shortest path
* @see rendezvous
*/
public def descend(source, potential) {
rep (path <- source) {
let nextStep = minHood(nbr([potential, self.getDeviceUID()]));
if (nextStep.size() > 1) {
let candidates = nbr([nextStep.get(1), path]);
source || anyHood([self.getDeviceUID(), true] == candidates)
} else { source }
}
}
/**
* Shortest path.
*
* @param source bool, whether the device is the source
* @param dest bool, whether the device is the destination
* @return bool, true if the device is in the shortest path
* @see descend, shortestPath
*/
public def rendezvous(source, dest) {
descend(source, distanceTo(dest))
}
/**
* Dynamically computes the shortest route between regions of a network, and
* dynamically adapts to shape and changes of the network topology. The �shortest path�
* is a Boolean field that is true for devices near the shortest route from a given
* (distributed) source to a (distributed) destination.
*
* @param source bool, whether the device is the source
* @param dest bool, whether the device is the destination
* @return bool, true if the device is in the shortest path
* @see rendezvous
*/
public def shortestPath(source, destination) {
rep (path <- false) {
mux (source) {
true
} else {
// any device on the shortest path
anyHood(
// check whether a neigh is on the shortest path AND the current device is in the shortest path
nbr (path) &&
(distanceTo(destination) == nbr( // if my distance is the same as the collected one
minHood( // get the closest distance
nbr(distanceTo(destination)) // get the neighbors distances from the destination
)
)
)
)
}
}
}
/**
* Entry point for a computation.
*
* @param source bool, whether the device is a source
* @param range num, spreading constraint
* @param f () -> T, entry point
* @param null T, default value
* @return T, apply f if device is inside the spreading region, null outside
*/
public def vm(source, range, f, null) {
vmWithMetric(source, nbrRange, range, f, null)
}
/**
* Entry point for a computation.
*
* @param source bool, whether the device is a source
* @param metric () -> num, how to estimate neighbors distances
* @param range num, spreading constraint
* @param f () -> T, entry point
* @param null T, default value
* @return T, apply f if device is inside the spreading region, null outside
*/
public def vmWithMetric(source, metric, range, f, null) {
boundSpreadingWithRange(() -> {
closerThanWithMetric(source, metric, range)
}, f, null)
}
/**
* Computing a Voronoi partition is an operation that is frequently useful in
* distributed systems. Given an initial set of seed devices, a Voronoi
* partition assigns each device to the partition of the nearest seed,
* effectively breaking the network up into zones of influence around key
* elements.
*
* @param source bool, whether the device is a seed
* @param id T, partition id
* @return T, partition of the nearest seed
*/
public def voronoiPatitioning(source, id) {
voronoiPatitioningWithMetric(source, id, nbrRange)
}
/**
* Computing a Voronoi partition is an operation that is frequently useful in
* distributed systems. Given an initial set of seed devices, a Voronoi
* partition assigns each device to the partition of the nearest seed,
* effectively breaking the network up into zones of influence around key
* elements.
*
* @param source bool, whether the device is a seed
* @param id T, partition id
* @param metric () -> num, how to estimate the distances of the neighbors
* @return T, partition of the nearest seed
*/
public def voronoiPatitioningWithMetric(seed, id, metric) {
G(seed, id, metric, identity)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy