Network.java: Difference between revisions
From Santa Fe Institute Events Wiki
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[[Base model]] | |||
<pre> | |||
/* | /* | ||
* Network.java | * Network.java | ||
Line 713: | Line 716: | ||
public static void setModel(CoopNetBlue m){model = m;} | public static void setModel(CoopNetBlue m){model = m;} | ||
} | } | ||
</pre> |
Latest revision as of 04:02, 16 June 2006
/* * Network.java * * Created on January 18, 2005, 4:09 PM * Modified June 14, 2006 * * This class generates a network, runs some * net statistics, and writes it to a pajek-formatted file */ package CoopNetBlue; //import java.util.Random; import uchicago.src.sim.network.NetworkFactory; import uchicago.src.sim.network.EdgeFactory; import java.util.Formatter; import uchicago.src.sim.util.Random; import java.util.ArrayList; import uchicago.src.sim.gui.OvalNetworkItem; import rlriolo.ioutils.*; import java.io.PrintWriter; import java.util.HashSet; import uchicago.src.sim.util.*; import java.util.Vector; /** * * @author Jack Waddell */ public class Network { //******************************************************* // static parameters // the main model public static CoopNetBlue model; //******************************************************* // Instance parameters public int[][] adjacencyMatrix; // Yes, it is Aij = 1 if j -> i. public int networkSize; // The number of agents public int connectRadius; // The radius for grid or SWN inits public double reconnectProb; // The prob or (re)wiring in (SWN) or random net // a pointer to the agent list, public ArrayList<CustomNode> agentList = new ArrayList<CustomNode>(); // These are for writing a pajek-formatted file protected String pajekFileName = "pajek"; protected String outputDirName = "./"; protected PrintWriter pajekFile, plaintextPajekFile; //////////////////////////////////////////////////////////////////////// // Constructor public Network(int networkSize, int connectRadius, double reconnectProb){ this.networkSize = networkSize; this.connectRadius = connectRadius; this.reconnectProb = reconnectProb; } /////////////////////////////////////////////////////////////////////// // buildAdjacencyMatrix // Inputs: int netType, selects which specific type of matrix to form // Outputs: int[][], the adjacency matrix public int[][] buildAdjacencyMatrix(int netType){ switch(netType){ case 0 : return buildAdjacencyMatrix2DWS(); case 1 : return buildAdjacencyMatrixWS(); case 2 : return buildAdjacencyMatrixRand(); default: return buildAdjacencyMatrix2DWS(); } } /////////////////////////////////////////////////////////////////////////// // // buildAdjacencyMatrixWS // Develops an adjacency matrix for a Watts-Strogatz Small World // network based on the given parameters. Note that this // implementation uses a disconnecting rewire, so that it is // possible to disconnect groups in the network. It is also // possible to have less than an average degree of 2x connectRadius, // since a connection can be "overwritten" during the rewire. // // Inputs: double reconnectProb: each neighbor connection // has a probability p of being disconnected from the outgoing side (i) // and reattached to a random node (including the one from which it // was just disconnected, and any other nodes that j goes to.)] // connectRadius: the number of neighbors to either side of each node. // Note that this often leads to cycles. public int[][] buildAdjacencyMatrixWS(){ adjacencyMatrix = new int[networkSize][networkSize]; // Make the regular gride for(int i = 0; i < networkSize; i++){ for(int j = i; j< networkSize; j++){ if( (j <= (i + connectRadius) ) && (i!=j) ){ adjacencyMatrix[i][j] = 1; adjacencyMatrix[j][i] = 1; } else if( (j >= (networkSize - connectRadius + i) ) && (i!=j)){ adjacencyMatrix[i][j] = 1; adjacencyMatrix[j][i] = 1; } else{ adjacencyMatrix[i][j] = 0; adjacencyMatrix[j][i] = 0; } } } // Do random rewiring double randomDouble; for(int i = 0; i < networkSize; i++){ for(int j = 1; j < networkSize; j++){ randomDouble = model.getUniformDoubleFromTo(0,1); if((randomDouble < reconnectProb)&& (adjacencyMatrix[i][j]==1)){ adjacencyMatrix[i][j] = 0; int randomi = j; do{ randomi = model.getUniformIntFromTo(0, networkSize - 1); if(model.rDebug > 2) System.out.printf("j = %d, randomi = %d, A[i][j] = %d\n", j,randomi, adjacencyMatrix[randomi][j]); } while (randomi == j || adjacencyMatrix[randomi][j] ==1); adjacencyMatrix[randomi][j] = 1; adjacencyMatrix[j][randomi] = 1; } } } return adjacencyMatrix; } /////////////////////////////////////////////////////////////////////////// // // buildAdjacencyMatrix2DWS // Develops an adjacency matrix for a Toroidal - Watts-Strogatz Small // World network based on the given parameters. Note that this // implementation uses a disconnecting rewire, so that it is // possible to disconnect groups in the network. public int[][] buildAdjacencyMatrix2DWS(){ // Make regular grid adjacencyMatrix = new int[networkSize][networkSize]; int ix, iy, jx, jy; int size = (int) Math.floor(Math.sqrt(networkSize)); System.out.printf("Size = %d \n", size); for(int i = 0; i < networkSize; i++){ for(int j = i; j< networkSize; j++){ ix = i % size; iy = i / size; jx = j % size; jy = j / size; double dx = Math.min( Math.min( Math.pow(jx - ix,2), Math.pow(jx + size - ix, 2)), Math.pow(jx - size - ix, 2) ); double dy = Math.min( Math.min( Math.pow(jy - iy,2), Math.pow(jy + size - iy, 2)), Math.pow(jy - size - iy, 2) ); if( (Math.sqrt(dx + dy) <= (connectRadius) ) && (i!=j) ){ adjacencyMatrix[i][j] = 1; adjacencyMatrix[j][i] = 1; } else{ adjacencyMatrix[i][j] = 0; adjacencyMatrix[j][i] = 0; } } } double randomDouble; // Do random rewiring for(int i = 0; i < networkSize; i++){ for(int j = 1; j < networkSize; j++){ randomDouble = model.getUniformDoubleFromTo(0,1); if((randomDouble < reconnectProb)&& (adjacencyMatrix[i][j]==1)){ adjacencyMatrix[i][j] = 0; int randomi = j; do{ randomi = model.getUniformIntFromTo(0, networkSize - 1); System.out.printf("j = %d, randomi = %d, A[i][j] = %d\n", j,randomi, adjacencyMatrix[randomi][j]); } while (randomi == j || adjacencyMatrix[randomi][j] ==1); adjacencyMatrix[randomi][j] = 1; adjacencyMatrix[j][randomi] = 1; } } } System.out.printf("----> Finished 2DWS Adjacency Mat\n"); return adjacencyMatrix; } /////////////////////////////////////////////////////////////////////////// // // buildAdjacencyMatrixStar // Develops an adjacency matrix for a Star Network, centered on i. public int[][] buildAdjacencyMatrixStar(int i){ adjacencyMatrix = new int[networkSize][networkSize]; int ix, iy, jx, jy; for(int k = 0; k < networkSize; k++){ for(int j = 0; j< networkSize; j++){ adjacencyMatrix[k][j] = 0; adjacencyMatrix[j][k] = 0; } } for(int j = 0; j< networkSize; j++){ if(i!=j){ adjacencyMatrix[i][j] = 1; adjacencyMatrix[j][i] = 1; } } System.out.printf("----> Finished Star Adjacency Mat\n"); return adjacencyMatrix; } ////////////////////////////////////////////////////////////////// // buildAdjacencyMatrixRand // Develops a symmetric, random adjacency matrix, so that the // probability of an edge existing between any pair of nodes is // reconnectProb. public int[][] buildAdjacencyMatrixRand(){ adjacencyMatrix = new int[networkSize][networkSize]; int i, j; double randn; for(i = 0; i < networkSize; i++){ for(j = 0; j < networkSize; j++){ randn = model.getUniformDoubleFromTo(0, 1); if (randn < reconnectProb){ adjacencyMatrix[i][j] = 1; adjacencyMatrix[j][i] = 1; } //else // System.out.printf("Randn = %f vs %f\n", randn, reconnectProb); } } System.out.printf("----> Finished Random Adjacency Mat\n"); return adjacencyMatrix; } /////////////////////////////////////////////////////////////////////// // buildAgentList // Develops an arrayList of CustomNodes interconnected based on the // adjacency matrix developed. public void buildAgentList(){ // Create all the agents for(int i = 0; i < networkSize; i++){ OvalNetworkItem drawable = new OvalNetworkItem(0,0); double strategy = model.getUniformDoubleFromTo(0, 1); CustomNode agent = new CustomNode(drawable, strategy); agentList.add(agent); } // Create the edges between them, governed by the adjacency // matrix CustomEdge edge; double cc; CustomNode jnode, inode; for(int i = 0; i < networkSize; i++){ for(int j = 0; j < networkSize; j++){ if(adjacencyMatrix[i][j] == 1){ jnode = (CustomNode) agentList.get(j); inode = (CustomNode) agentList.get(i); edge = new CustomEdge(jnode, inode); jnode.addOutEdge(edge); inode.addInEdge(edge); // This symmetritizes the network // i.e. makes undirected edge = new CustomEdge(inode, jnode); inode.addOutEdge(edge); jnode.addInEdge(edge); } } } } ///////////////////////////////////////////////////////////// // printAdjacencyMatrix // a debugging tool. Prints the adjacency matrix to the terminal public void printAdjacencyMatrix(){ System.out.printf("--- Printing Adjacency Matrix, size %d ---\n", networkSize); for(int i = 0; i < networkSize; i++){ for(int j = 0; j < networkSize; j++){ System.out.printf(" %d ", adjacencyMatrix[i][j]); } System.out.printf("\n"); } } ////////////////////////////////////////////////////////////// // writePajekNetwork // Writes the network to a file in pajek // format. Note: this version writes DOS type line feeds. public void writePajekNetwork(ArrayList<CustomNode> agentList){ String verts, arcs; // These are carriage return and line feed in DOS format. char cr = (char) 13; char lf = (char) 10; // pajek requires the vertices and arcs separately. verts = String.format("*Vertices %d%c%c", networkSize, cr, lf); arcs = String.format("*Arcs %c%c", cr, lf); // step through all nodes for(int i = 0; i < networkSize; i++){ CustomNode inode = (CustomNode) agentList.get(i); verts += String.format("%d \"N%d: %d\"", inode.getID() + 1, inode.getID(), inode.getUtility()); verts += String.format(" ic %s%c%c", inode.getMyPajekColor(),cr, lf); ArrayList edgesInList = inode.getInEdges(); int numEdges = edgesInList.size(); CustomNode testNode = (CustomNode) (model.agentList).get(i); if (testNode != inode) System.out.printf("Nodes(%d) not equal\n", i); if ( (testNode.getOutDegree() != inode.getOutDegree()) || (testNode.getInDegree() != inode.getInDegree())) System.out.printf("Nodes(%d) have different degree\n", i); if (numEdges > 0) // if node has at least one neighbor, write the edges for(int j = 0; j < numEdges; j++){ CustomEdge edge = (CustomEdge)edgesInList.get(j); arcs += String.format("%d %d %c%c", ((CustomNode)edge.getFrom()).getID() + 1, ((CustomNode)edge.getTo()).getID() + 1, cr, lf); } } String s = verts + arcs; writeToPajekFile(s); } ///////////////////////////////////////////////////////////// // writeLineToPajekFile // writes a single line to the pajek file public void writeLineToPajekFile ( String line ) { if ( pajekFile == null ) { return; } else { pajekFile.println( line ); } } ////////////////////////////////////////////////////////// // writeToPajekFile // Does the same. public void writeToPajekFile ( String line ) { if ( pajekFile == null ) { return; } else { pajekFile.print( line ); } } ////////////////////////////////////////////////////////////// // startPajekFile // opens a file to write the pajek network to. public PrintWriter startPajekFile () { if ( model.rDebug > 0 ) System.out.println( "startPajekFile called!" ); pajekFile = null; String fullFileName = pajekFileName + String.format( "%02d.net", model.runNumber ); pajekFile = IOUtils.openFileToWrite( outputDirName, fullFileName, "r" ); if ( model.rDebug > 0 ) System.out.println( "startPajekFile completed!" ); return pajekFile; } ////////////////////////////////////////////////////////////// // startPajekFile - overload // opens a file to write the pajek network to. Calls it // by integer i public PrintWriter startPajekFile (int i) { if ( model.rDebug > 0 ) System.out.println( "startPajekFile called!" ); pajekFile = null; String fullFileName = pajekFileName + String.format( "%03d.%02d.net", i, model.runNumber ); pajekFile = IOUtils.openFileToWrite( outputDirName, fullFileName, "r" ); if ( model.rDebug > 0 ) System.out.println( "startPajekFile completed!" ); return pajekFile; } ////////////////////////////////////////////////////////// // endPajekFile // closes the open pajekFile public void endPajekFile ( ) { IOUtils.closePWFile( pajekFile ); } /////////////////////////////////////////////////////////// // getAverageCC1 // Calculates the average 1-neighborhood clustering coefficient public double getAverageCC1(){ CustomNode node = null; double sum = 0; for(int i = 0; i < agentList.size(); i ++){ node = (CustomNode) agentList.get(i); sum += getNodeCC1(node); } return sum / (double) agentList.size(); } ////////////////////////////////////////////////////////// // getAverageCC2 // Calculates the average 2-neighborhood clustering coefficient public double getAverageCC2(){ CustomNode node = null; double sum = 0; for(int i = 0; i < agentList.size(); i ++){ node = (CustomNode) agentList.get(i); sum += getNodeCC2(node); } return sum / (double) agentList.size(); } ///////////////////////////////////////////////////////// // union // Support function. // Returns the union of two array lists of nodes public ArrayList<CustomNode> union(ArrayList<CustomNode> l1, ArrayList<CustomNode> l2){ ArrayList<CustomNode> unionList = new ArrayList<CustomNode>(); unionList.addAll(l1); for(int i = 0; i < l2.size(); i ++){ CustomNode node = (CustomNode) l2.get(i); if (!unionList.contains(node)) unionList.add(node); } return unionList; } ///////////////////////////////////////////////////////////// // intersection // Support function // Return the intersection of two array lists of nodes public ArrayList<CustomNode> intersection(ArrayList<CustomNode> l1, ArrayList<CustomNode> l2){ ArrayList<CustomNode> interList = new ArrayList<CustomNode>(); for(int i = 0; i < l1.size(); i ++){ CustomNode node = (CustomNode) l1.get(i); if (l2.indexOf(node) >-1) interList.add(node); } return interList; } ///////////////////////////////////////////////////////////// // getNodeCC1 // Computes the clustering coefficient CC1, as per Pajek documentation // This is the 1-neighborhood clustering coefficient public double getNodeCC1 (CustomNode node){ ArrayList<CustomNode> neighborsList = new ArrayList<CustomNode>(); // Get all neighbors neighborsList = union(node.getOutNodes(), node.getInNodes()); int sum = 0; int k = neighborsList.size(); for(int j = 0; j < k; j ++){ CustomNode jnode = (CustomNode) neighborsList.get(j); ArrayList<CustomNode> nOut = jnode.getOutNodes(); ArrayList<CustomNode> nIn = jnode.getInNodes(); sum += (intersection(nOut, neighborsList)).size(); sum += (intersection(nIn, neighborsList)).size(); } double cc1 = 0; if (k > 1) cc1 = (double)sum/( 2* (double)k * (double)(k-1)); return cc1; } ///////////////////////////////////////////////////////////// // getNodeCC2 // computes the clustering coefficient CC2, as per Pajek documentation // E(G1(v))/E(G2(v)) // This is the 2-neighboorhood clustering coefficient public double getNodeCC2 (CustomNode node){ // calc E(G1(v)) = sum1 ArrayList<CustomNode> neighbors1List = new ArrayList<CustomNode>(); ArrayList<CustomNode> neighbors2List = new ArrayList<CustomNode>(); neighbors1List = union(node.getOutNodes(), node.getInNodes()); neighbors2List.addAll(neighbors1List); int sum1 = 0; int k = neighbors1List.size(); for(int j = 0; j < k; j ++){ CustomNode jnode = (CustomNode) neighbors1List.get(j); ArrayList<CustomNode> nOut = jnode.getOutNodes(); ArrayList<CustomNode> nIn = jnode.getInNodes(); sum1 += (intersection(nOut, neighbors1List)).size(); //sum1 += (intersection(nIn, neighbors1List)).size(); neighbors2List = union(neighbors2List, union(nOut, nIn)); } //System.out.printf("For node %d sum1 = %d\n", node.getID(), sum1); int index = neighbors2List.indexOf(node); while (index > 0){ //System.out.printf("node index = %d\n", index); neighbors2List.remove(index); index = neighbors2List.indexOf(node); } // calc E(G2(v)) = sum2 int sum2 = 0; int ind1, ind2; for(int j = 0; j < neighbors2List.size(); j++){ CustomNode jnode = (CustomNode) neighbors2List.get(j); ArrayList<CustomNode> nOut = jnode.getOutNodes(); ArrayList<CustomNode> nIn = jnode.getInNodes(); sum2 += (intersection(nOut, neighbors2List)).size(); //sum2 += (intersection(nIn, neighbors2List)).size(); ind1 = neighbors2List.indexOf(jnode); ind2 = neighbors2List.lastIndexOf(jnode); if (ind1 != ind2) System.out.printf ("Node %d in list multiple times\n", jnode.getID()); } //System.out.printf("For node %d sum1 = %d\n", node.getID(), sum2); double cc2 = 0; if (sum2 > 0) cc2 = (double)sum1/(double)sum2; return cc2; } ///////////////////////////////////////////////////////// // printList // Debug tool // Prints the contents of an ArrayList public void printList(ArrayList<CustomNode> list){ for(int i = 0; i < list.size(); i++){ CustomNode node = (CustomNode) list.get(i); System.out.printf("%d, ", node.getID()); } System.out.printf("\n"); } /////////////////////////////////////////////////////////// // PickRandomEdge // Picks a random edge with uniform probability in O(m/(n*n)) // (I think) public CustomEdge pickRandomEdge(){ CustomEdge edge = null; CustomNode inode; CustomNode jnode; do{ inode = agentList.get(model.getUniformIntFromTo(0, agentList.size() -1)); do{ jnode = agentList.get(model.getUniformIntFromTo(0, agentList.size() -1)); } while (inode == jnode); if ( (jnode.getOutNodes()).contains(inode)) edge = getEdgeFromTo(jnode, inode); } while (edge == null); return edge; } /////////////////////////////////////////////////////////// // selectRandomUncoupledPair // Selectrs a random pair of nodes with uniform probability. public CustomNode[] selectRandomUncoupledPair(){ boolean pass = false; CustomNode inode, jnode; int i, j; CustomEdge edge; do{ i = model.getUniformIntFromTo(0, agentList.size() -1); do{ j = model.getUniformIntFromTo(0, agentList.size() -1); } while (i == j); inode = (CustomNode) agentList.get(i); jnode = (CustomNode) agentList.get(j); if ( !(jnode.getOutNodes()).contains(inode)){ pass = true; } } while (!pass); CustomNode[] nodes = {inode, jnode}; return nodes; } //////////////////////////////////////////////////////////// // selectRandomUncoupledNode // public CustomNode selectRandomUncoupledNode(CustomNode jnode){ boolean pass = false; CustomNode inode = null; int i, j = jnode.getID(); CustomEdge edge; // get a list of the nodes, but make sure it isn't the main list // 'cause we're gonna shuffle it ArrayList <CustomNode> nodesList = new ArrayList<CustomNode>(); nodesList.addAll(agentList); SimUtilities.shuffle(nodesList, Random.uniform); i = 0; int k = 0; do{ inode = (CustomNode) nodesList.get(i); if (inode != jnode){ if ( !(jnode.getOutNodes()).contains(inode)){ pass = true; } } i++; if (i == nodesList.size()){ i = 0; k ++; } } while ( !pass && k < 2 ); if (k == 2){ do{ i = model.getUniformIntFromTo(0, agentList.size() - 1); inode = (CustomNode) agentList.get(i); } while ( i == j || (jnode.getOutNodes()).contains(inode)); } return inode; } // getters and setters public String getPajekFileName () { return pajekFileName; } public void setPajekFileName ( String s ) { pajekFileName = s; } public String getOutputDirName () { return outputDirName; } public void setOutputDirName ( String s ) { outputDirName = s; } public int getNetworkSize() {return networkSize;} public ArrayList<CustomNode> getAgentList() {return agentList;} public PrintWriter getPajekFile () { return pajekFile; } public CustomEdge getEdgeFromTo(CustomNode jnode, CustomNode inode){ CustomEdge edge; HashSet edgeList = inode.getEdgesFrom(jnode); Object[] edges = edgeList.toArray(); // get the edge object connected to jnode edge = ((CustomEdge)edges[0]); return edge; } //************************************************** // Static Methods public static void setModel(CoopNetBlue m){model = m;} }