package i5.las2peer.services.ocd.adapters.coverInput;
import i5.las2peer.services.ocd.adapters.AdapterException;
import i5.las2peer.services.ocd.adapters.Adapters;
import i5.las2peer.services.ocd.graphs.Cover;
import i5.las2peer.services.ocd.graphs.CustomGraph;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.la4j.matrix.Matrix;
import org.la4j.matrix.sparse.CCSMatrix;
import y.base.Node;
import y.base.NodeCursor;
/**
* A cover input adapter for the community member list format.
* Each line of input contains first the name of a community (optional) and then the names of the member nodes, using the space character (' ') as a delimiter.
* Nodes will be considered to have an equal membership degree for each community they are associated with.
* @author Sebastian
*
*/
public class CommunityMemberListsCoverInputAdapter extends AbstractCoverInputAdapter {
/**
* States whether only the member node names or also the community names are given.
* @param areCommunityNamesDefined If false, each line of input is considered to only contain the names of the member nodes without a community name in the beginning.
* If true, each line must first contain the community name.
*/
private boolean communityNamesDefined = false;
/**
* Creates a new standard instance.
*/
CommunityMemberListsCoverInputAdapter(){
}
/**
* Creates a new instance setting the reader attribute.
* @param reader A reader that will be used to receive input from.
*/
CommunityMemberListsCoverInputAdapter(Reader reader) {
this.reader = reader;
}
public boolean areCommunityNamesDefined() {
return communityNamesDefined;
}
public void setCommunityNamesDefined(boolean communityNamesDefined) {
this.communityNamesDefined = communityNamesDefined;
}
@Override
public Cover readCover(CustomGraph graph) throws AdapterException {
String nodeName;
String communityName;
Map<String, List<Integer>> nodeCommunities = new HashMap<String, List<Integer>>();
List<Integer> communityIndices;
Map<Integer, String> communityNames = new HashMap<Integer, String>();
int communityCount = 0;
try {
List<String> line = Adapters.readLine(reader);
/*
* Reads edges
*/
while (line.size() >= 1) {
int i=0;
if(communityNamesDefined) {
communityName = line.get(0);
communityNames.put(communityCount, communityName);
i++;
}
for(; i<line.size(); i++) {
nodeName = line.get(i);
if (!nodeCommunities.containsKey(nodeName)) {
communityIndices = new ArrayList<Integer>();
communityIndices.add(communityCount);
nodeCommunities.put(nodeName, communityIndices);
} else {
nodeCommunities.get(nodeName).add(communityCount);
}
}
communityCount++;
line = Adapters.readLine(reader);
}
} catch (Exception e) {
throw new AdapterException(e);
} finally {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Matrix memberships = new CCSMatrix(graph.nodeCount(), communityCount);
NodeCursor nodes = graph.nodes();
Node node;
while(nodes.ok()) {
node = nodes.node();
nodeName = graph.getNodeName(node);
communityIndices = nodeCommunities.get(nodeName);
if(communityIndices != null) {
for(int communityIndex : communityIndices) {
memberships.set(node.index(), communityIndex, 1d/communityIndices.size());
}
}
nodes.next();
}
Cover cover = new Cover(graph, memberships);
if(communityNamesDefined) {
for(int i : communityNames.keySet()) {
cover.setCommunityName(i, communityNames.get(i));
}
}
return cover;
}
}