protelis.coord.meta.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:meta
import protelis:coord:accumulation
import protelis:coord:meta:timereplication
import protelis:coord:sparsechoice
import protelis:coord:spreading
import protelis:lang:utils
import java.lang.Double.POSITIVE_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
}
}
/*
* Gossip active sources.
*
* @param source bool, whether the device is a source
* @return [deviceUID], list of sources' ids
*/
public def findSources(source) {
let k = 5;
findSourcesWithId(source, getUID(), roundTripTime(diameter(S(POSITIVE_INFINITY, nbrRange))) / (k - 1), k)
}
/*
* Gossip active sources.
*
* @param source bool, whether the device is a source
* @param id T, source identifier
* @param d num, network diameter
* @param k num, time replicated replicas
* @return [T], list of sources' ids
*/
public def findSourcesWithId(source, id, d, k) {
timeReplicatedWithK(
() -> {
share(v, nbrV <- []) {
v.union(unionHood(nbrV))
.union(if (source) { [id] } else { [] })
}
}, [id], d, k)
}
/**
* Run an instance of a function for every source id.
*
* @param sources [T], sources in the system
* @param f (T) -> T', function to be applied for every source
* @param null T', default value
* @return [T'], list of results coming from the executed instances
*/
public def multiInstance(sources, f, null) {
alignedMap(
nbr(sources.map(self, id -> {[id, null]})),
(key, field) -> { sources.contains(key) },
(key, field) -> { f.apply(key) },
null
)
}
/**
* Splice devices into regions according to the discriminant and apply f.
*
* @param discriminant T, split regions according to this value
* @param filter (T) -> bool, how to handle the discriminant value
* @param function () -> T', what to apply in each region
* @param default T', default value
* @return T', apply f or default
*/
public def multiRegion(discriminant, filter, function, default) {
if (filter.apply(discriminant)) {
let res = alignedMap(
nbr([[discriminant, default]]),
(key, field) -> { filter.apply(key) },
(key, field) -> { function.apply() },
default
);
if (res == []) { default } else { res.get(0).get(1) }
} else { default }
}
/**
* Feed f with pre-processed data.
*
* @param input G, input
* @param pre (G) -> H, how to pre-process
* @param f (H) -> I, what to do
* @return I, f(pre(input))
*/
public def preProcessAndApply(input, pre, f) {
f.apply(pre.apply(input))
}
/**
* Feed f with pre-processed data, and then post-process the output.
*
* @param input G, input
* @param pre (G) -> H, how to pre-process
* @param f (H) -> I, what to do
* @param post (I) -> T, how to post process
* @return T, post(f(pre(input)))
*/
public def processAndApply(input, pre, f, post) {
post.apply(f.apply(pre.apply(input)))
}
/**
* Apply f, and then post-process the output.
*
* @param input G, input
* @param f (H) -> I, what to do
* @param post (I) -> T, how to post process
* @return T, post(f(input))
*/
public def postProcessAndApply(input, f, post) {
post.apply(f.apply(input))
}
/**
* Publish/Subscribe pattern.
*
* @param publisher bool, who publishes
* @param subscriber bool, who is subscribing
* @param information T, what to share
* @param null T, what to share if you are neither a subscriber nor a
* publisher
* @return T, information if the device is a publisher, a
* subscriber or is in the shortest path between them.
* null otherwise
*/
public def publishSubscribe(publisher, subscriber, information, null) {
publishSubscribeWithPotential(distanceTo(publisher), subscriber, information, null)
}
/**
* Publish/Subscribe pattern.
*
* @param potential num, aggregation direction (publisher are devices whose
* potential is 0)
* @param subscriber bool, who is subscribing
* @param information T, what to share
* @param null T, what to share if you are neither a subscriber nor a
* publisher
* @return T, information if the device is a publisher, a
* subscriber or is in the shortest path between them.
* null otherwise
*/
public def publishSubscribeWithPotential(potential, subscriber, information, null) {
if (C(potential, or, subscriber, false)) {
gradcast(potential == 0, information, potential, identity)
} else {
null
}
}