Go back to NetworkGeneration

<project-file type=“source”/>

<content> #include <genrand2.h> #include <iostream> #include <fstream> #include <algorithm> #include <set> #include <time.h> #include “parameters.h”

class Link { public:

  Link(int n, bool type) : neighbor(n), internal(type) {}
  int node() const { return neighbor; }
  bool operator == (int n) const { return neighbor == n; }
  void dump() const {
      std::cout<<neighbor<<((internal)?"h":"e");
  }
  bool internal;

private:

  int neighbor;

};

class Node { public:

  int degree() const { return links.size(); }
  int isNeighbor(int node) const {
      return std::find(links.begin(), links.end(), node) == links.end();
  }
  void connect(int node, bool internal) {
      std::vector<Link>::iterator i = std::find(links.begin(), links.end(), node);
      if (i == links.end())
          links.push_back(Link(node, internal));
      else
          i->internal = internal;
  }
  const std::vector<Link> &neighbors() const { return links; }
  void dump() const {
      int n = links.size();
      for (int i = 0; i < n; i++)
          links[i].dump();
      std::cout<<std::endl;
  }
  int id;

private:

  std::vector<Link> links;

};

class Net { public:

  Net(int population);
  void connect(int i, int j, bool internal, bool directed = false);
  bool connected(int i, int j) { return nodes[i].isNeighbor(j); }
  int degree(int i) const { return nodes[i].degree(); }
  const std::vector<int> connectedComponent(int i) const;
  int maximumDegree() { return M; }
  int population() { return nodes.size(); }
  void dump() const;

private:

  int M;
  std::vector<Node> nodes;
  void traverse(int node, std::vector<bool> &visited) const;

};

Net::Net(int population)

  : nodes(population)

{

  M = 0;
  for (int i = 0; i < population; i++)
      nodes[i].id = i;

}

void Net::connect(int i, int j, bool internal, bool directed) {

  nodes[i].connect(j, internal);
  int k = nodes[i].degree();
  if (M < k) M = k;
  if (!directed) {
      nodes[j].connect(i, internal);
      k = nodes[j].degree();
      if (M < k) M = k;
  }

}

const std::vector<int> Net::connectedComponent(int i) const {

  int n = nodes.size();
  std::vector<bool> connected(n, false);
  traverse(i, connected);
  std::vector<int> component(n);
  std::vector<int>::iterator j = component.begin();
  for (int i = 0; i < n; i++)
      if (connected[i]) *j++ = i;
  component.erase(j, component.end());
  return component;

}

void Net::traverse(int node, std::vector<bool> &visited) const {

  visited[node] = true;
  const std::vector<Link> &neighbors = nodes[node].neighbors();
  std::vector<Link>::const_iterator i;
  for (i = neighbors.begin(); i != neighbors.end(); i++)
      if(!visited[i->node()]) traverse(i->node(), visited);

}

void Net::dump() const {

  int n = nodes.size();
  for (int i = 0; i < n; i++) nodes[i].dump();

}

class Households { public:

  Households(int n, SimDistribution *household_size_dist);
  Households(const Households &);
  ~Households();
  int populationSize() const { return population_size; }
  int householdSize(int i) const { return household_sizes[i]; }
  int inHousehold(int node) const { return in_household[node]; }
  int nodeNotInHousehold(int node, int house) const;
  int randomInHousehold(int i) const {
      return households[i][genrand2i() % household_sizes[i]];
  }
  int nodeInHouse(int i, int j) const { return households[i][j]; }
  void combine(int i, int j);
  int houseHolds() const { return households.size(); }

private:

  std::vector<int *> households;
  std::vector<int> in_household;
  std::vector<int> household_sizes;
  int population_size;
  void move(int i, int j);

};

Households::Households(const Households &hh)

  : households(hh.houseHolds()), household_sizes(hh.household_sizes), in_household(hh.in_household)

{

int n = hh.houseHolds(), m, *p, *q;
for (int i = 0; i < n; i++) {
	m = hh.householdSize(i);
              p = (int*) malloc(sizeof(int) * m);
	q = hh.households[i];
	for (int j = 0; j < m ; j++) p[j] = q[j];
	households[i] = p;
}
  population_size = hh.populationSize();

}

Households::Households(int n, SimDistribution *household_size_dist)

  : households(n), household_sizes(n)

{

  population_size = 0;
  int k;
  for (int i = 0; i < n; i++) {
      k = (int) household_size_dist->draw();
      population_size += household_sizes[i] = k;
      households[i] = (int*) malloc(sizeof(int) * k);
  }
  in_household.resize(population_size);
  for (int i = 0, k = 0; i < n; i++)
      for (int j = 0; j < household_sizes[i]; j++) {
          households[i][j] = k;
          in_household[k] = i;
          ++k;
      }

}

Households::~Households() {

  int n = households.size();
  for (int i = 0; i < n; i++) free(households[i]);

}

int Households::nodeNotInHousehold(int node, int house) const {

  int m, n = households.size();
  for (int i = 0; i < n; i++) if (i != house) {
      m = household_sizes[i];
      if (node < m) return households[i][node];
      node -= m;
  }

} void Households::combine(int i, int j) {

  move(j, i);
  households[j] = NULL;
  move(households.size() - 1, j);
  households.pop_back();

}

void Households::move(int j, int i) {

  int m = household_sizes[i];
  int n = household_sizes[j];
  household_sizes[i] = m + n;
  household_sizes[j] = 0;
  int *p = (int*) realloc(households[i], sizeof(int)*(m + n));
  int *q = households[j];
  for (int k = 0; k < n; k++) {
      in_household[q[k]] = i;
      p[k + m] = q[k];
  }
  free(households[j]);
  households[i] = p;
  households[j] = NULL;

}

generate an integer i such that 0 ⇐ i < n, and i != m inline int genrand2i(int n, int m) { if (m >= n) return genrand2i() % n; int k = genrand2i() % (n - 1); if (k < m) return k; return k + 1; } int main(int argc, const char *argv[]) { Parameters params; BoolArgument ArgType(“random-on-household”, “if true, construct a random network of households, otherwise construct a random network of individuals”, Argument::REQUIRED); IntArgument ArgHouseholds(“households”, “number of households”, Argument::REQUIRED); IntArgument ArgM(“M”, “maximum allowable external degree”, Argument::NOT_REQUIRED); FloatArgument ArgAvgk(“average-degree”, “average degree”, Argument::REQUIRED); DistributionArgument ArgHouseholdSize(“household-size”, “the household size distributionr”, Argument::REQUIRED); LongArgument ArgSeed(“seed”, “the seed to initialize the random number generator”, Argument::NOT_REQUIRED); ArgHouseholdSize.setEnableDiscrete(true); ArgHouseholdSize.setEnableExp(false); ArgHouseholdSize.setEnableNormal(false); ArgHouseholdSize.setEnableGamma(false); ArgHouseholdSize.setEnableExp(false); ArgHouseholdSize.setEnableNULL(false); params.addArgument(ArgHouseholds); params.addArgument(ArgType); params.addArgument(ArgM); params.addArgument(ArgAvgk); params.addArgument(ArgHouseholdSize); params.addArgument(ArgSeed); if (!params.parse(argc, argv)) { params.usage(argv[0]); return 1; } int households = ArgHouseholds.value(); int M = ArgM.value(); bool random_on_household = ArgType.value(); float avgk = ArgAvgk.value(); SimDistribution *household_size_dist = ArgHouseholdSize.value(); time_t seed; if (ArgSeed.set()) seed = ArgSeed.value(); else time(&seed); sgenrand2(seed); Households hh(households, household_size_dist); Net net(hh.populationSize()); internal connections

  for (int i = 0; i < households; i++) {
      int n = hh.householdSize(i);
      for (int j = 0; j < n; j++)
          for (int k = j + 1; k < n; k++)
              net.connect(hh.nodeInHouse(i, j), hh.nodeInHouse(i, k), true);
  }
  // connected components
  Households components(hh);
  // total number of links
  int links = (int)(avgk * hh.populationSize() / 2);
  if (links < households - 1) {
      std::cerr<<"Too few edges, cannot make a connected graph"<<std::endl;
      return 1;
  }
  int k = 0, n, m, i, j;
  while (k < links) {
      m = components.houseHolds();
      if (random_on_household) {
          int h1 = genrand2i() % m;
          int h2 = genrand2i(m, h1);
          i = components.randomInHousehold(h1);
          j = components.randomInHousehold(h2);
      }
      else {
          i = genrand2i() % components.populationSize();
          int house = components.inHousehold(i);
          int total = components.populationSize() - components.householdSize(house);
          int h = genrand2i() % total;
          j = components.nodeNotInHousehold(h, house);
      }
      if (net.degree(i) == M || net.degree(j) == M) continue;
      net.connect(i, j, false);
      components.combine(components.inHousehold(i), components.inHousehold(j));
      if (components.houseHolds() == 1) break;
      k++;
  }
  m = hh.houseHolds();
  while (k < links) {
      if (random_on_household) {
          int h1 = genrand2i() % m;
          int h2 = genrand2i(m, h1);
          i = hh.randomInHousehold(h1);
          j = hh.randomInHousehold(h2);
      }
      else {
          i = genrand2i() % hh.populationSize();
          while (true) {
              j = genrand2i(hh.populationSize(), i);
              if (hh.inHousehold(i) != hh.inHousehold(j)) break;
          }
      }

#define external_degree(i) (net.degree(i) - hh.householdSize(hh.inHousehold(i)) + 1)

      if (external_degree(i) == M || external_degree(j) == M) continue;
      net.connect(i, j, false);
      k++;
  }
  net.dump();
  return 0;

} </content> <use name=“genrand2.h”/> <use name=“parameters.h”/>