protelis.coord.sparsechoice.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:sparsechoice
import protelis:coord:spreading
import java.lang.Double.POSITIVE_INFINITY
def default() {
[POSITIVE_INFINITY, POSITIVE_INFINITY]
}
def breakUsingUids(uid, grain, metric) {
share (lead, nbrLead <- uid) {
distanceCompetition(distanceToWithMetric(uid == lead, metric), nbrLead, uid, grain, metric)
} == uid
}
def distanceCompetition(d, nbrLead, uid, grain, metric) {
mux (d > grain) {
uid
} else {
let thr = 0.5 * grain;
mux (d >= thr) {
default()
} else {
foldMin(
mux (nbr(d) + metric() >= thr) {
default()
} else {
nbrLead
}
)
}
}
}
def randomUid() {
rep (v <- [self.nextRandomDouble(), self.getDeviceUID()]) {
v
}
}
/**
* Devices compete against one another to become local leaders,
* resulting in a random Voronoi partition with a characteristic
* grain size.
*
* @param grain num, partition dimension
* @param metric () -> num, estimate distance from the leader
* @return bool, true if the current device is the leader, false otherwise
*/
public def S(grain, metric) {
breakUsingUids(randomUid(), grain, metric)
}
/**
* Multi-leader election based on a symmetry breaking value, presented at ACSOS 2022.
* Implemented from Self-stabilising Priority-Based Multi-Leader Election and Network Partitioning.
* Find more at https://ieeexplore.ieee.org/document/9935012
*
* @param localId num, local identifier
* @param radius num, extension of the local candidacy
* @param strength num, power of the local device candidacy
* @param metric () -> num, estimated distance from neighbors
* @return bool, true if the current device is the leader, false otherwise
*/
public def boundedElection(localId, radius, strength, metric) {
let local = Candidacy(-strength, 0, localId)
let worstCandidacy = Candidacy(POSITIVE_INFINITY, POSITIVE_INFINITY, POSITIVE_INFINITY)
candidacyLeaderId(
share (received <- local) {
let candidacies = received.set(1, candidacyDistance(received) + metric())
let shouldBeDiscarded = candidacyLeaderId(candidacies) == localId // myself
|| candidacyDistance(candidacies) >= radius // too far away
let filtered = mux (shouldBeDiscarded) { worstCandidacy } else { candidacies }
min(local, foldMin(worstCandidacy, filtered))
}
)
}
/*
* Support functions for boundedElection
*/
def Candidacy(symmetryBreaker, distance, leaderId) = [symmetryBreaker, distance, leaderId]
def candidacyDistance(candidacy) = candidacy.get(1)
def candidacyLeaderId(candidacy) = candidacy.get(2)