Ejemplo n.º 1
0
int main(long argc, char** argv) {
  int i, j;
  long t;
  FILE* fp;

  double duration;
  clock_t time;
  struct timeval tpstart, tpend;
  long iTimeInterval;

  int Test = 0;

  if (argc != 4) {
    printf("usage: %s .max_graph_file num_threads GR frequency\n", argv[0]);
    exit(-1);
  }
  num_threads = atoi(argv[2]);
  fprintf(stderr, "Threads: \t\t%d\n", num_threads);

  // initialize the graph, will read the graph from a file.
  fp = fopen(argv[1], "r");
  if (!fp) {
    printf("Cannot open %s\n", argv[1]);
    exit(-1);
  }

  char tag;
  char str[5];
  int from, to, capacity;

  fscanf(fp, "%c", &tag);
  while (tag != 'p') {
    while (getc(fp) != '\n')
      ;
    fscanf(fp, "%c", &tag);
  }
  fscanf(fp, "%s %d %d", str, &g_num_nodes, &g_num_edges);

  gr_threshold = (int)(atof(argv[3]) * g_num_nodes);
  fprintf(stderr, "GR Freq: \t\t%2.2f\n", atof(argv[3]));
  fprintf(stderr, "%d nodes, %d edges\n\n", g_num_nodes, g_num_edges);

  // initialize graph
  init_graph();

  // read and sort edges
  Edge edge = (Edge)malloc(2 * g_num_edges * sizeof(struct edge_entry));
  if (edge == NULL)
    exit(-1);
  edge_sym = edge;
  edgecnt = 0;
  for (i = 0; i < g_num_edges;) {
    if (getc(fp) == 'a') {
      fscanf(fp, "%d	%d	%d/n", &from, &to, &capacity);
      edge = Addedge(from - 1, to - 1, capacity, 0, edge);
      i++;
    }
  }
  assert(i == g_num_edges);

  SortEdges();
  fprintf(stderr, "Edge sorted!\n");

  // initialize thread parameters
  init_threads(num_threads);
  pthread_t threads[num_threads];

  // initial barrier and lock
  pthread_mutex_init(&(gr_mutex), NULL);
  node_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t) * g_num_nodes);
  if (node_mutex == NULL)
    exit(-1);
  thread_mutex =
      (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t) * num_threads);
  if (thread_mutex == NULL)
    exit(-1);
  for (i = 0; i < num_threads; i++) {
    pthread_mutex_init(&(thread_mutex[i]), NULL);
  }
  for (i = 0; i < g_num_nodes; i++) {
    pthread_mutex_init(&(node_mutex[i]), NULL);
  }

  pthread_barrier_init(&start_barrier, NULL, num_threads);

  // now the f c e h arrays have been initialized. start the threads
  // so that they can work asynchronously.
  time = clock();
  gettimeofday(&tpstart, NULL);
  preflow(num_threads);
  for (t = 0; t < num_threads; t++) {
    pthread_create(&(threads[t]), NULL, scan_nodes, (void*)t);
  }
#ifdef MONITOR
  int num_idle_threads;
  int totalQsize, global_Q_size;
  while (!flow_done()){
    gettimeofday(&tpend, NULL);
    iTimeInterval = 1000000 * (tpend.tv_sec - tpstart.tv_sec);
    iTimeInterval += tpend.tv_usec - tpstart.tv_usec;
    duration = (double)iTimeInterval / 1000000;
    totalQsize = 0;
    num_idle_threads = 0;
    for (j = 0; j < num_threads; j++) {
      totalQsize += threadEnv[j].Qsize;
      if (threadEnv[j].Qsize == 0)
        num_idle_threads++;
    }
    if (duration > 10.0) {
                fprintf(stderr, " totalQsize: %8d globalQsize %4d idle %2d\n",
       totalQsize, global_Q_size, num_idle_threads);
              fflush(stderr);
                  exit(-1);
    }
    // printf("%12d %12d \t\t totalQsize: %8d GR %4d idel %2d\n",
    // g_node[0].excess,g_node[g_num_nodes-1].excess, totalQsize, GRcnt,
    // num_idle_threads);
    // printf("%d\n", totalQsize);
  }
  printf("\n");
#endif

  for (t = 0; t < num_threads; t++) {
    pthread_join(threads[t], NULL);
  }
  gettimeofday(&tpend, NULL);
  time = clock() - time;

  iTimeInterval = 1000000 * (tpend.tv_sec - tpstart.tv_sec);
  iTimeInterval += tpend.tv_usec - tpstart.tv_usec;
  duration = (double)iTimeInterval / 1000000;

  fprintf(stderr, "FLOW: \t\t\t%ld\n", sink->excess);
  fprintf(stderr, "Wall Time: \t\t%5.3f\n", duration);
  fprintf(stderr,
          "CPU Time: \t\t%5.3f\n",
          (double)time / CLOCKS_PER_SEC / num_threads);
  fprintf(stderr, "Push: \t\t\t%ld\n", totalPushes);
  fprintf(stderr, "Push Efcy: \t\t%.1f\n", totalPushes / duration);
  fprintf(stderr, "Lift: \t\t\t%ld\n", totalLifts);
  fprintf(stderr, "Lift Efcy: \t\t%.1f\n", totalLifts / duration);
  fprintf(stderr, "GR: \t\t\t%d\n", GRcnt);
  fprintf(stderr, "HELP: \t\t\t%d\n", HPcnt);
  fflush(stderr);

  check_violation();

  pthread_exit(NULL);
}
Ejemplo n.º 2
0
//有上下界的最大流
static bool MaxFlow_Bound(Digraph& dg, ArcFilter& arc_filter, Digraph::Node s, Digraph::Node t, double Q, 
						  Capacity& low, Capacity& high, Flow& flow, bool fixTotalQ=false)
{
	typedef FilterArcs<Digraph, ArcFilter> Adaptor;
	typedef Adaptor::ArcMap<double> CapMap;
	typedef Adaptor::ArcMap<Digraph::Arc> LowUpArcMap;
	typedef Preflow<Adaptor,CapMap> FastPreFlow;

	//过滤后的图
	Adaptor adaptor(dg, arc_filter);

	//在源点s之前再添加一条分支,用来限制总流量Q
	Digraph::Node s0 = adaptor.addNode();
	Digraph::Arc e0 = adaptor.addArc(s0, s);
	low[e0] = (fixTotalQ?Q:0); high[e0] = Q; arc_filter[e0] = true; // 注:ArcFilter默认false

	//添加一条t->s的分支,下界0,上界无穷大
	Digraph::Arc ts = adaptor.addArc(t, s0);
	low[ts] = 0; high[ts] = DBL_MAX; arc_filter[ts] = true;

	//分支容量(默认无穷大)
	CapMap cap(adaptor, DBL_MAX);
	//上界分支拆分后的分支映射记录
	//e --> e=(u->v), ee1=(ss->v), e22=(u->tt)
	//lu[ee1] = e; lu[ee2] = e;
	LowUpArcMap lu(adaptor, INVALID);

	//添加超级源汇
	Digraph::Node ss = adaptor.addNode();
	Digraph::Node tt = adaptor.addNode();

	//注:后续新增的节点和分支属性map不会自动更新,需要手动设置
	//例如cap[e0]、cap[ts]、arc_filter、lu等
	//为了减少重复代码,将属性初始化声明转移到添加节点和分支之后
	//拆分有上下界的分支,其它分支上界默认无穷大
	for(Adaptor::ArcIt e(adaptor);e!=INVALID;++e)
	{
		if(low[e] > 0 && high[e] >= low[e])
		{
			Digraph::Node u = adaptor.source(e);
			Digraph::Node v = adaptor.target(e);
			Digraph::Arc ee1 = adaptor.addArc(ss, v);
			Digraph::Arc ee2 = adaptor.addArc(u, tt);
			cap[e] = high[e] - low[e];
			cap[ee1] = low[e]; cap[ee2] = low[e];   // 更新cap
			low[ee1] = 0; low[ee2] = 0;             // 更新low
			lu[ee1] = e; lu[ee2] = e;               // 更新lu
			arc_filter[ee1] = true; arc_filter[ee2] = true;
		}
		//cout<<"e"<<g .id(e)<<" low:"<<low[e]<<", high:"<<high[e]<<", cap:"<<cap[e]<<endl;
	}

	//执行一次最大流计算
	FastPreFlow preflow(adaptor, cap, ss, tt);
	preflow.run();
	//最大流值
	double max_flow = preflow.flowValue();
	//计算得到的分支流量
	const FastPreFlow::FlowMap& flow_map = preflow.flowMap();

	//判断是否可行流(即额外添加的分支满流,满足下界low)
	//2种方法:1) 所有的流量的下界之和是否等于最大流  2) 所有分支的下界是否满流
	//使用第1种方法判定: 计算所有分支的下界之和
	//用于后续判断是否可行流(满足下界,且下界之和等于最大流)
	double S = 0;
	for(Adaptor::ArcIt e(adaptor);e!=INVALID;++e)
	{
		S += low[e];
	}

	const double PRE_VNC_EPSILON=0.01;
	bool ret = (fabs(S-max_flow) < PRE_VNC_EPSILON);
	if(ret)
	{
		//有上下界的最大流分配成功!!!
		//得到计算的流量值,并记录拆分的分支
		EdgeArray edges;
		for(Adaptor::ArcIt ee(adaptor);ee!=INVALID;++ee)
		{
			flow[ee] = flow_map[ee];
			if(lu[ee] != INVALID)
			{
				edges.push_back(ee);
			}
		}

		typedef std::set<Digraph::Arc> ArcSet;
		//记录已处理的分支
		ArcSet aset;
		for(EdgeArray::iterator itr=edges.begin();itr!=edges.end();++itr)
		{
			Digraph::Arc ee = *itr;
			Digraph::Arc e = lu[ee];
			// 如果分支已处理,则添加到aset集合中,避免重复流量叠加
			if(aset.find(e) == aset.end())
			{
				flow[e] = low[e] + flow_map[e];
				aset.insert(e);
			}
		}
	}
	// erase(node)函数会自动删除节点以及节点的流入流出分支
	// erase(arc)函数则只会删除分支
	adaptor.erase(ss);
	adaptor.erase(tt);
	adaptor.erase(s0);

	return ret;
}