/* * sf_network.cpp * * Implementation of the SF_Network class * * Written by Alex Popkin * For Math 164 Final Project, Spring 2004 * March 14, 2004 */ #include "node.hpp" #include "sf_network.hpp" using namespace std; #define SUSCEPTIBLE 1 #define INFECTED 2 #define IMMUNE 3 #define HUB 4 #define NOTHUB 5 // Constructor SF_Network::SF_Network(int size_, bool time_) { V = size_; vertices = new Node*[V]; srand(static_cast(time(0))); int sumDegree = 8; int counter, rnd, ver; bool linked; int first, second; struct timeval start, end; // Timing code if (time_) { gettimeofday(&start, NULL); } vertices[0] = new Node(0); // Initial configuration vertices[1] = new Node(1); vertices[2] = new Node(2); vertices[3] = new Node(3); vertices[0]->addEdge(1); vertices[1]->addEdge(0); vertices[2]->addEdge(1); vertices[1]->addEdge(2); vertices[3]->addEdge(2); vertices[2]->addEdge(3); vertices[0]->addEdge(3); vertices[3]->addEdge(0); for (int a = 4; a < V; a++) { // Create the array of nodes vertices[a] = new Node(a); linked = false; counter = 0; ver = 0; first = -1; // Used to avoid double links second = -1; rnd = 1 + int(sumDegree * rand()/(RAND_MAX+1.0)); while (linked == false) { // This while loop makes the first link counter += vertices[ver]->getK(); if (rnd <= counter) { linked = true; vertices[a]->addEdge(ver); // Add the new edge vertices[ver]->addEdge(a); first = ver; } else { ver++; } } sumDegree += 2; linked = false; counter = 0; ver = 0; rnd = 1 + int(sumDegree * rand()/(RAND_MAX+1.0)); while (linked == false) { // This while loop makes the second link counter += vertices[ver]->getK(); if (rnd <= counter) { if ((ver != first) && (ver != a)) { linked = true; vertices[a]->addEdge(ver); vertices[ver]->addEdge(a); second = ver; } else { rnd = 1 + int(sumDegree * rand()/(RAND_MAX+1.0)); ver = 0; counter = 0; } } else { ver++; } } sumDegree += 2; // Degree has increased by two linked = false; counter = 0; ver = 0; rnd = 1 + int(sumDegree * rand()/(RAND_MAX+1.0)); while (linked == false) { // This while loop makes the third link counter += vertices[ver]->getK(); if (rnd <= counter) { if ((ver != first) && (ver != second) && (ver != a)) { linked = true; vertices[a]->addEdge(ver); vertices[ver]->addEdge(a); } else { rnd = 1 + int(sumDegree * rand()/(RAND_MAX+1.0)); ver = 0; counter = 0; } } else { ver++; } } sumDegree += 2; } if (time_) { // Print the time taken to create the network gettimeofday(&end, NULL); double fstart, fend; fstart = (start.tv_sec * 1000000.0 + start.tv_usec) / 1000000.0; fend = (end.tv_sec * 1000000.0 + end.tv_usec) / 1000000.0; cout << "Creation time was: " << fend - fstart << endl; } } // Destructor SF_Network::~SF_Network() { for (int b = 0; b < V; b++) { // Delete the vertices array delete vertices[b]; } delete [] vertices; } // Epi function, runs an epidemic simulation void SF_Network::epi(double init, double g, double lambda, int gens) { int totalImmune = 0; // Counts the nodes immunized at any given time // Immunize the correct number of hubs int* temp1 = new int [V]; // This array holds the number of for (int dd = 0; dd < V; dd++) { // vertices with each degree temp1[dd] = 0; } int mDegree; // Fill in the temp1 array for (int cc = 0; cc < V; cc++) { mDegree = vertices[cc]->getK(); temp1[mDegree]++; } int cutOff = V + 1; int hubC = 0; double hRatio, imrand; double extras; // Counts how many border cases shouldn't be immune if (g > 0.0) { for (int ee = V - 1; ee >= 0; ee--) { // Loops through the temp hubC += temp1[ee]; // array, counting nodes hRatio = (double) hubC / V; // until the correct ratio is if (hRatio > g) { // reached. extras = (double) hubC - (g * V); cout << "We have " << extras << " extras." << endl; extras = (double) extras / temp1[ee]; cout << "Probability of immunization is: " << 1.0 - extras << endl; cutOff = ee; cout << "Cutoff is: " << cutOff << endl; ee = -1; } } } int tempCounter = 0; for (int ff = 0; ff < V; ff++) { if (vertices[ff]->getK() > cutOff) { // Immunize the hubs vertices[ff]->immunize(); totalImmune++; } else if (vertices[ff]->getK() == cutOff) { // Border case imrand = (double) rand()/RAND_MAX; if (imrand > extras) { vertices[ff]->immunize(); totalImmune++; tempCounter++; /* cout << "Immunized " << ff << " where k = " << vertices[ff]->getK() << endl; */ } } } cout << "Border cases immunized: " << tempCounter << endl; double irand; // double gamma = 0.0; // Percentage of hubs not immunized /* // This for loop removes immunity from a certain percentage of hubs for (int loopgam = 0; loopgam < V; loopgam++) { irand = (double) rand()/RAND_MAX; if (irand < gamma) { vertices[loopgam]->suscept(); } } */ // Randomly infect the correct percentage of nodes at the start for (int loopi = 0; loopi < V; loopi++) { irand = (double) rand()/RAND_MAX; if (irand < init) { // Random decision for each vertex vertices[loopi]->infect(); } } /************* Code for actual infection model run starts here. ********/ // This array tells whether nodes are at risk of infection bool* inDanger = new bool [V]; int numInf = 0; double chanceS = .1; double chanceI = .1; for (int t = 0; t < gens; t++) { // Adust immunities based on random probabilities for (int cImm = 0; cImm < V; cImm++) { irand = (double) rand()/RAND_MAX; if (irand > chanceS) { if (vertices[cImm]->getStatus() == IMMUNE) { totalImmune--; } vertices[cImm]->suscept(); } irand = (double) rand()/RAND_MAX; if ((irand > chanceI) && (vertices[cImm]->Htype == HUB)) { if (vertices[cImm]->getStatus() != IMMUNE) { totalImmune++; } vertices[cImm]->immunize(); } } for (int setD = 0; setD < V; setD++) { inDanger[setD] = false; // Start out with no one in danger } numInf = 0; // Total number infected // This for loop moves through the vertex array, noting neighbors // of infected vertices for (int abc = 0; abc < V; abc++) { if (vertices[abc]->getStatus() == INFECTED) { vertices[abc]->spread(inDanger); } } // This for loop enforces the rule that an infected vertex gets // cured after one timestep. for (int loopInf = 0; loopInf < V; loopInf++) { if (vertices[loopInf]->getStatus() == INFECTED) { vertices[loopInf]->cure(); // inDanger[loopInf] = false; // Won't be infected next step } } // This for loop infects nodes in danger with probability lambda for (int loopV = 0; loopV < V; loopV++) { if (inDanger[loopV]) { irand = (double) rand()/RAND_MAX; // Randomly infect nodes if (irand < lambda) { // that are in danger numInf++; vertices[loopV]->infect(); } } } // Print number infected cout << "Generation: " << t << " # infected is:" << numInf ; cout << " Total immune is: " << totalImmune << endl ; } delete [] temp1; // Free memory delete [] inDanger; } // printK function, prints statistics about the connectivity of the network void SF_Network::printK(int incr) { int sl = (V / incr) + 1; // Numbers of baskets int* temp = new int [sl]; for (int d = 0; d < sl; d++) { temp[d] = 0; } int myDegree; for (int c = 0; c < V; c++) { // Count the number of vertices myDegree = vertices[c]->getK(); // with each degree temp[myDegree / incr]++; } for (int e = 0; e < sl; e++) { // Print results if (temp[e] > 0) { cout << e * incr << "-" << (e+1) * incr - 1 << ": " ; cout << temp[e] << endl; } } delete [] temp; } /* Junk to make emacs use the right C++ style when editing this code: * Local Variables: * c-file-style: "stroustrup" * End: */