/********************************************************** * Doctoral Program in Science and Information Technology * Department of Informatics Engineering * University of Coimbra ********************************************************** * Large Scale Concurrent Systems * * Pedro Alexandre Mesquita Santos Martins - pamm@dei.uc.pt * Nuno Manuel dos Santos Antunes - nmsa@dei.uc.pt **********************************************************/ package org.graphdht.benchmark; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.FileWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Random; /** * Created by IntelliJ IDEA. * User: alex * Date: 8/Jun/2010 * Time: 16:15:18 * To change this template use File | Settings | File Templates. */ public class RichGetRicher { protected long totalDegree = 0; private final String graphname; private final Random random; private final String filename; /** * * @param random * @param filename */ public RichGetRicher(String graphname, Random random, String filename) { this.graphname = graphname; this.random = random; this.filename = filename; } /** * * @param initialOrder initial number of nodes from where the algorithm is started * @param order final number of nodes that the graph is meant to have at the end * @param m number of connections that should be established when a new node is added to the graph */ public void generateGraphBAModel(int initialOrder, int order, int m) { Node randomNode = null, newNode = null; List<Node> graphNodes = generateInitialGraph(initialOrder, order); for (int i = initialOrder; i < order - 1; i++) { newNode = new Node(i); for (int j = 0; j < m; j++) { randomNode = getRandomNodeFrom(graphNodes); // System.out.println(randomNode); graphNodes = connect(graphNodes, newNode.getId(), randomNode.getId()); } } writeToFile(graphNodes); } void writeToFile(List<Node> graph) { System.out.println("RichGetRicher size: " + graph.size()); try { // Create file FileWriter fstream = new FileWriter(filename); BufferedWriter out = new BufferedWriter(fstream); out.write("graph " + graphname + "{\n"); double sum = 0; int max = 0, min = Integer.MAX_VALUE; for (Node n : graph) { out.write(n.toDotLanguage()); int i = n.relations.size(); if (i > max) { max = i; } if (i < min) { min = i; } sum += i; } out.write("}\n"); out.close(); System.out.println("AVG: " + (sum / graph.size())); System.out.println("min = " + min); System.out.println("max = " + max); System.out.println("-----------------------"); StringBuilder sb = new StringBuilder(graphname); sb.append("\n").append("RichGetRicher size:\t " + graph.size()).append("\n"); sb.append("AVG: \t" + (sum / (double) graph.size())).append("\n"); sb.append("min: \t" + min).append("\n"); sb.append("max: \t" + max).append("\n"); Collections.sort(graph, new Comparator<Node>() { public int compare(Node o1, Node o2) { return o2.relations.size() - o1.relations.size(); } }); sb.append("Number of Relations:\n"); for (Node n : graph) { sb.append(n.relations.size()).append("\n"); } FileOutputStream fosDist = new FileOutputStream(filename + ".xls"); fosDist.write(sb.toString().getBytes()); fosDist.close(); } catch (Exception e) {//Catch exception if any System.err.println("Error: " + e.getMessage()); } } Node getRandomNodeFrom(List<Node> graph) { int f = (int) (random.nextDouble() * totalDegree); int accumulator = 0; Node node; for (int i= 0; i < graph.size() - 1; i++) { node = graph.get(i); accumulator += node.degree; if (accumulator >= f) { return node; } } return null; } /** * Generates a Graph where all nodes have at least degree 1. * If not like this the node would never join the network */ List<Node> generateInitialGraph(int initialOrder, int order) { if (initialOrder % 2 == 0) { initialOrder = initialOrder >> 1 << 1; //make it an even number } List<Node> graph = new ArrayList<Node>(order); Node n1, n2; for (int i = 0; i < order; i = i + 2) { n1 = new Node(i); n2 = new Node(i + 1); graph.add(n1); graph.add(n2); graph = connect(graph, n1.id, n2.id); } return graph; } /** * Connects two nodes in the graph. * Assumes that both nodes are already in the graph. * @param nodes * @param n1 * @param n2 * @return */ List<Node> connect(List<Node> nodes, long n1, long n2) { Node node1 = nodes.get((int) n1); Node node2 = nodes.get((int) n2); node1.connectTo(node2); node2.connectTo(node1); return nodes; } class Node { long id; List<Long> relations = new ArrayList<Long>(); int degree = 0; Node() { } public Node(long id) { super(); this.id = id; } public long getId() { return this.id; } public void connectTo(Node n) { assert (this.relations != null); assert (this != null); this.relations.size(); for (Long l : this.relations) { if (l == n.getId()) { this.degree++; totalDegree++; return; } } this.degree++; totalDegree++; this.relations.add(n.id); } public String toString() { return this.toDotLanguage(); } public String toDotLanguage() { StringBuilder sb = new StringBuilder(); for (Long rel : relations) { sb.append(" ").append(this.id).append(" -- ").append(rel.intValue()).append(";\n"); } return sb.toString(); } } }