/*
* @(#)KCLiqueCommunityDetection.java
*
* Copyright 2010 by University of Pittsburgh, released under GPLv3.
*/
package routing.community;
import java.util.*;
//import routing.communitydetection.DiBuBB.Duration;
import core.*;
/**
*
Performs the K-Clique Community Detection algorithm described in
* Distributed Community Detection in Delay Tolerant Networks by Pan
* Hui et al. (bibtex record is included below for convenience). A node using
* K-Clique keeps a record of all the nodes it has met and the cummulative
* contact duration it has had with each. Once this total contact duration for
* one of these nodes exceeds a configurable parameter, the node is added to the
* host's familiar set and local community and the node's familiar set is added
* to an approximation of all the familiar sets of the host's local community.
*
* Note: In ONE, each KCliqueCommunityDetection stores a reference to another
* node's familiar set instead of creating and managing a duplicate of it.
*
* When two peers meet, they exchange familiar sets, local community sets,
* and their respective approximations of the familiar sets of their local
* communities. If the nodes are not part of each other's local communities,
* the set intersection between the local community of one host and the familiar
* set of its peer is computed. If the size of this intersection is
* greater than the configurable parameter, K, the peer has K nodes
* in common with the local community and should therefore be added to the local
* community. In this case, then, the peer's local community may have other
* nodes that also share K nodes in common with the local community, which then
* should be added to it as well.
*
*
* \@inproceedings{1366929,
* Address = {New York, NY, USA},
* Author = {Hui, Pan and Yoneki, Eiko and Chan, Shu Yan and Crowcroft, Jon},
* Booktitle = {MobiArch '07: Proceedings of 2nd ACM/IEEE international workshop
* on Mobility in the evolving internet architecture},
* Doi = {http://doi.acm.org/10.1145/1366919.1366929},
* Isbn = {978-1-59593-784-8},
* Location = {Kyoto, Japan},
* Pages = {1--8},
* Publisher = {ACM},
* Title = {Distributed Community Detection in Delay Tolerant Networks},
* Year = {2007}
* }
*
*
* @author PJ Dillon, University of Pittsburgh
*/
public class KCliqueCommunityDetection implements CommunityDetection
{
public static final String K_SETTING = "K";
public static final String FAMILIAR_SETTING = "familiarThreshold";
protected Set familiarSet;
protected Set localCommunity;
protected Map> familiarsOfMyCommunity;
protected double k;
protected double familiarThreshold;
public KCliqueCommunityDetection(Settings s)
{
this.k = s.getDouble(K_SETTING);
this.familiarThreshold = s.getDouble(FAMILIAR_SETTING);
}
public KCliqueCommunityDetection(KCliqueCommunityDetection proto)
{
this.k = proto.k;
this.familiarThreshold = proto.familiarThreshold;
familiarSet = new HashSet();
localCommunity = new HashSet();
this.familiarsOfMyCommunity = new HashMap>();
}
public void newConnection(DTNHost myHost, DTNHost peer,
CommunityDetection peerCD)
{
KCliqueCommunityDetection scd = (KCliqueCommunityDetection)peerCD;
// Ensure each node is in its own local community
// (This is the first instance where we actually get the host for these
// objects)
this.localCommunity.add(myHost);
scd.localCommunity.add(peer);
/*
* The first few steps of the protocol are
* (1) update my local approximation of my peer's familiar set
* (2) merge my and my peer's local approximations of our respective
* community's familiar sets
*
* In both these cases, for ONE, each CommunityDetection object stores a
* reference to the familiar set of its community members. As those members
* update their familiar set, others storing a reference to that set
* immediately witness the reflected changes. Therefore, we don't have to
* anything to update an "approximation" of the familiar sets. They're not
* approximations here anymore. In this way, what we have in the k-Clique
* community detection class is an upper bound on the performance of the
* protocol.
*/
// Add peer to my local community if needed
if(!this.localCommunity.contains(peer))
{
/*
*
*/
// compute the intersection size
int count=0;
for(DTNHost h : scd.familiarSet)
if(this.localCommunity.contains(h))
count++;
// if peer familiar has K nodes in common with this host's local community
if(count >= this.k - 1)
{
this.localCommunity.add(peer);
this.familiarsOfMyCommunity.put(peer, scd.familiarSet);
// search the peer's local community for other nodes with K in common
// (like a transitivity property)
for(DTNHost h : scd.localCommunity)
{
if(h == myHost || h == peer) continue;
// compute intersection size
count = 0;
for(DTNHost i : scd.familiarsOfMyCommunity.get(h))
if(this.localCommunity.contains(i))
count++;
// add nodes if there are K in common with this local community
if(count >= this.k - 1)
{
this.localCommunity.add(h);
this.familiarsOfMyCommunity.put(h,
scd.familiarsOfMyCommunity.get(h));
}
}
}
}
// Repeat process from peer's perspective
if(!scd.localCommunity.contains(myHost))
{
int count = 0;
for(DTNHost h : this.familiarSet)
if(scd.localCommunity.contains(h))
count++;
if(count >= scd.k - 1)
{
scd.localCommunity.add(myHost);
scd.familiarsOfMyCommunity.put(myHost, this.familiarSet);
for(DTNHost h : this.localCommunity)
{
if(h == myHost || h == peer) continue;
count = 0;
for(DTNHost i : this.familiarsOfMyCommunity.get(h))
if(scd.localCommunity.contains(i))
count++;
if(count >= scd.k - 1)
{
scd.localCommunity.add(h);
scd.familiarsOfMyCommunity.put(h,
this.familiarsOfMyCommunity.get(h));
}
}
}
}
}
public void connectionLost(DTNHost myHost, DTNHost peer,
CommunityDetection peerCD, List history)
{
if(this.familiarSet.contains(peer)) return;
// Compute cummulative contact duration with this peer
Iterator i = history.iterator();
double time = 0;
while(i.hasNext())
{
Duration d = i.next();
time += d.end - d.start;
}
// If cummulative duration is greater than threshold, add
if(time > this.familiarThreshold)
{
KCliqueCommunityDetection scd = (KCliqueCommunityDetection)peerCD;
this.familiarSet.add(peer);
this.localCommunity.add(peer);
this.familiarsOfMyCommunity.put(peer, scd.familiarSet);
}
}
public boolean isHostInCommunity(DTNHost h)
{
return this.localCommunity.contains(h);
}
public CommunityDetection replicate()
{
return new KCliqueCommunityDetection(this);
}
public Set getLocalCommunity()
{
return this.localCommunity;
}
}