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); }
//有上下界的最大流 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; }