bool vertex_separator_flow_solver::construct_flow_pb( const PartitionConfig & config, graph_access & G, PartitionID & lhs, PartitionID & rhs, std::vector<NodeID> & lhs_nodes, std::vector<NodeID> & rhs_nodes, std::vector<NodeID> & new_to_old_ids, long *n_ad, long* m_ad, node** nodes_ad, arc** arcs_ad, long ** cap_ad, node** source_ad, node** sink_ad, long* node_min_ad, EdgeID & no_edges_in_flow_graph) { //very dirty for loading variables :). some time this should all be refactored. for now we can focus on the important stuff. #include "../refinement/quotient_graph_refinement/flow_refinement/flow_solving_kernel/convert_ds_variables.h" //building up the graph as in parse.h of hi_pr code //first we have to count the number of edges // s to lhs + rhs to t + lhs to rhs unsigned no_edges = 0; for( unsigned i = 0; i < lhs_nodes.size(); i++) { NodeID node = lhs_nodes[i]; forall_out_edges(G, e, node) { NodeID target = G.getEdgeTarget(e); if(rhs == G.getPartitionIndex(target)) { ++no_edges; } } endfor }
void graph_extractor::extract_block(graph_access & G, graph_access & extracted_block, PartitionID block, std::vector<NodeID> & mapping) { // build reverse mapping std::vector<NodeID> reverse_mapping; NodeID nodes = 0; NodeID dummy_node = G.number_of_nodes() + 1; forall_nodes(G, node) { if(G.getPartitionIndex(node) == block) { reverse_mapping.push_back(nodes++); } else { reverse_mapping.push_back(dummy_node); } } endfor extracted_block.start_construction(nodes, G.number_of_edges()); forall_nodes(G, node) { if(G.getPartitionIndex(node) == block) { NodeID new_node = extracted_block.new_node(); mapping.push_back(node); extracted_block.setNodeWeight( new_node, G.getNodeWeight(node)); forall_out_edges(G, e, node) { NodeID target = G.getEdgeTarget(e); if( G.getPartitionIndex( target ) == block ) { EdgeID new_edge = extracted_block.new_edge(new_node, reverse_mapping[target]); extracted_block.setEdgeWeight(new_edge, G.getEdgeWeight(e)); } } endfor }
void cycle_search::find_random_cycle(graph_access & G, std::vector<NodeID> & cycle) { //first perform a bfs starting from a random node and build the parent array std::deque<NodeID>* bfsqueue = new std::deque<NodeID>; NodeID v = random_functions::nextInt(0, G.number_of_nodes()-1); bfsqueue->push_back(v); std::vector<bool> touched(G.number_of_nodes(),false); std::vector<bool> is_leaf(G.number_of_nodes(),false); std::vector<NodeID> parent(G.number_of_nodes(),0); std::vector<NodeID> leafes; touched[v] = true; parent[v] = v; while(!bfsqueue->empty()) { NodeID source = bfsqueue->front(); bfsqueue->pop_front(); bool is_leaf = true; forall_out_edges(G, e, source) { NodeID target = G.getEdgeTarget(e); if(!touched[target]) { is_leaf = false; touched[target] = true; parent[target] = source; bfsqueue->push_back(target); } } endfor if(is_leaf) leafes.push_back(source); }
int graph_io::writeGraphWeighted(graph_access & G, std::string filename) { std::ofstream f(filename.c_str()); f << G.number_of_nodes() << " " << G.number_of_edges()/2 << " 11" << std::endl; forall_nodes(G, node) { f << G.getNodeWeight(node) ; forall_out_edges(G, e, node) { f << " " << (G.getEdgeTarget(e)+1) << " " << G.getEdgeWeight(e) ; } endfor
int mis_permutation::calculate_tightness(NodeID node, graph_access & G) { int tightness = 0; forall_out_edges(G, edge, node) { NodeID target = G.getEdgeTarget(edge); bool target_index = G.getPartitionIndex(target); if (target_index == 1) { tightness++; } } endfor
EdgeWeight quality_metrics::edge_cut(graph_access & G) { EdgeWeight edgeCut = 0; forall_nodes(G, n) { PartitionID partitionIDSource = G.getPartitionIndex(n); forall_out_edges(G, e, n) { NodeID targetNode = G.getEdgeTarget(e); PartitionID partitionIDTarget = G.getPartitionIndex(targetNode); if (partitionIDSource != partitionIDTarget) { edgeCut += G.getEdgeWeight(e); } } endfor
EdgeID edge_cut_flow_solver::regions_no_edges( graph_access & G, std::vector<NodeID> & lhs_boundary_stripe, std::vector<NodeID> & rhs_boundary_stripe, PartitionID & lhs, PartitionID & rhs, std::vector<NodeID> & outer_lhs_boundary_nodes, std::vector<NodeID> & outer_rhs_boundary_nodes ) { EdgeID no_of_edges = 0; unsigned idx = 0; for( unsigned i = 0; i < lhs_boundary_stripe.size(); i++, idx++) { NodeID node = lhs_boundary_stripe[i]; bool is_outer_boundary = false; forall_out_edges(G, e, node) { if(G.getPartitionIndex(G.getEdgeTarget(e)) == BOUNDARY_STRIPE_NODE) no_of_edges++; else is_outer_boundary = true; } endfor if(is_outer_boundary) { outer_lhs_boundary_nodes.push_back(idx); } } for( unsigned i = 0; i < rhs_boundary_stripe.size(); i++, idx++) { NodeID node = rhs_boundary_stripe[i]; bool is_outer_boundary = false; forall_out_edges(G, e, node) { if(G.getPartitionIndex(G.getEdgeTarget(e)) == BOUNDARY_STRIPE_NODE) no_of_edges++; else is_outer_boundary = true; } endfor if(is_outer_boundary) { outer_rhs_boundary_nodes.push_back(idx); } } return no_of_edges; }
// for documentation see technical reports of christian schulz void contraction::contract(const PartitionConfig & partition_config, graph_access & G, graph_access & coarser, const Matching & edge_matching, const CoarseMapping & coarse_mapping, const NodeID & no_of_coarse_vertices, const NodePermutationMap & permutation) const { if(partition_config.combine) { coarser.resizeSecondPartitionIndex(no_of_coarse_vertices); } std::vector<NodeID> new_edge_targets(G.number_of_edges()); forall_edges(G, e) { new_edge_targets[e] = coarse_mapping[G.getEdgeTarget(e)]; } endfor std::vector<EdgeID> edge_positions(no_of_coarse_vertices, UNDEFINED_EDGE); //we dont know the number of edges jet, so we use the old number for //construction of the coarser graph and then resize the field according //to the number of edges we really got coarser.start_construction(no_of_coarse_vertices, G.number_of_edges()); NodeID cur_no_vertices = 0; forall_nodes(G, n) { NodeID node = permutation[n]; //we look only at the coarser nodes if(coarse_mapping[node] != cur_no_vertices) continue; NodeID coarseNode = coarser.new_node(); coarser.setNodeWeight(coarseNode, G.getNodeWeight(node)); if(partition_config.combine) { coarser.setSecondPartitionIndex(coarseNode, G.getSecondPartitionIndex(node)); } // do something with all outgoing edges (in auxillary graph) forall_out_edges(G, e, node) { visit_edge(G, coarser, edge_positions, coarseNode, e, new_edge_targets); } endfor
void local_optimizer::run_maxent_optimization_internal( const Config & config, graph_access & G ) { if(G.number_of_edges() == 0) return; std::vector< coord_t > new_coord(G.number_of_nodes()); CoordType alpha = config.maxent_alpha; int iterations = config.maxent_inner_iterations; CoordType q = config.q; std::vector<CoordType> distances(G.number_of_edges(),0); configure_distances( config, G, distances); for( int i = 0; i < config.maxent_outer_iterations; i++) { CoordType norm_coords = 0; CoordType norm_diff = 0; do { forall_nodes_parallel(G, node) { CoordType rho_i = 0; // assume graph is connected? if(G.getNodeDegree(node) == 0) continue; forall_out_edges(G, e, node) { CoordType distance = distances[e]; rho_i += 1/(distance*distance); } endfor rho_i = 1/rho_i; CoordType S_x = 0; CoordType S_y = 0; CoordType n_S_x = 0; CoordType n_S_y = 0; forall_out_edges(G, e, node) { NodeID target = G.getEdgeTarget(e); CoordType diffX = G.getX(node) - G.getX(target); CoordType diffY = G.getY(node) - G.getY(target); CoordType dist_square = diffX*diffX+diffY*diffY; CoordType distance = distances[e]; CoordType dist = sqrt(dist_square); CoordType scaled_distance = distance/dist; CoordType squared_distance = distance*distance; S_x += (G.getX(target) + scaled_distance*diffX)/(squared_distance); S_y += (G.getY(target) + scaled_distance*diffY)/(squared_distance); CoordType dist_q = pow(dist, q+2); n_S_x -= diffX/dist_q; n_S_y -= diffY/dist_q; } endfor S_x *= rho_i; S_y *= rho_i; forall_nodes(G, target) { if( node == target ) continue; CoordType diffX = G.getX(node) - G.getX(target); CoordType diffY = G.getY(node) - G.getY(target); CoordType dist_square = diffX*diffX+diffY*diffY; CoordType dist = sqrt(dist_square); CoordType dist_q = pow(dist, q+2); n_S_x += diffX/dist_q; n_S_y += diffY/dist_q; } endfor CoordType mult_factor = alpha*rho_i; n_S_x *= mult_factor; n_S_y *= mult_factor; new_coord[node].x = S_x + sgn(q)*n_S_x; new_coord[node].y = S_y + sgn(q)*n_S_y; } endfor
EdgeWeight edge_cut_flow_solver::convert_ds( const PartitionConfig & config, graph_access & G, PartitionID & lhs, PartitionID & rhs, std::vector<NodeID> & lhs_boundary_stripe, std::vector<NodeID> & rhs_boundary_stripe, std::vector<NodeID> & new_to_old_ids, long *n_ad, long* m_ad, node** nodes_ad, arc** arcs_ad, long ** cap_ad, node** source_ad, node** sink_ad, long* node_min_ad, EdgeID & no_edges_in_flow_graph) { //should soon be refactored #include "convert_ds_variables.h" //building up the graph as in parse.h of hi_pr code NodeID idx = 0; new_to_old_ids.resize(lhs_boundary_stripe.size() + rhs_boundary_stripe.size()); std::unordered_map<NodeID, NodeID> old_to_new; for( unsigned i = 0; i < lhs_boundary_stripe.size(); i++) { G.setPartitionIndex(lhs_boundary_stripe[i], BOUNDARY_STRIPE_NODE); new_to_old_ids[idx] = lhs_boundary_stripe[i]; old_to_new[lhs_boundary_stripe[i]] = idx++ ; } for( unsigned i = 0; i < rhs_boundary_stripe.size(); i++) { G.setPartitionIndex(rhs_boundary_stripe[i], BOUNDARY_STRIPE_NODE); new_to_old_ids[idx] = rhs_boundary_stripe[i]; old_to_new[rhs_boundary_stripe[i]] = idx++; } std::vector<NodeID> outer_lhs_boundary; std::vector<NodeID> outer_rhs_boundary; EdgeID no_edges = regions_no_edges(G, lhs_boundary_stripe, rhs_boundary_stripe, lhs, rhs, outer_lhs_boundary, outer_rhs_boundary); no_edges_in_flow_graph = no_edges; if(outer_lhs_boundary.size() == 0 || outer_rhs_boundary.size() == 0) return false; n = lhs_boundary_stripe.size() + rhs_boundary_stripe.size() + 2; //+source and target m = no_edges + outer_lhs_boundary.size() + outer_rhs_boundary.size(); nodes = (node*) calloc ( n+2, sizeof(node) ); arcs = (arc*) calloc ( 2*m+1, sizeof(arc) ); arc_tail = (long*) calloc ( 2*m, sizeof(long) ); arc_first= (long*) calloc ( n+2, sizeof(long) ); acap = (long*) calloc ( 2*m, sizeof(long) ); arc_current = arcs; node_max = 0; node_min = n; unsigned nodeoffset = 1; source = n - 2 + nodeoffset; sink = source+1; idx = 0; for( unsigned i = 0; i < lhs_boundary_stripe.size(); i++, idx++) { NodeID node = lhs_boundary_stripe[i]; NodeID sourceID = idx + nodeoffset; forall_out_edges(G, e, node) { if(G.getPartitionIndex(G.getEdgeTarget(e)) == BOUNDARY_STRIPE_NODE) { NodeID targetID = old_to_new[G.getEdgeTarget(e)] + nodeoffset; EdgeWeight capacity = G.getEdgeWeight(e); tail = sourceID; head = targetID; cap = capacity; createEdge() } } endfor }
void two_way_fm::move_node_back(const PartitionConfig & config, graph_access & G, const NodeID & node, vertex_moved_hashtable & moved_idx, refinement_pq * from_queue, refinement_pq * to_queue, PartitionID from, PartitionID to, boundary_pair * pair, NodeWeight * from_part_weight, NodeWeight * to_part_weight, complete_boundary & boundary) { ASSERT_NEQ(from, to); ASSERT_EQ(from, G.getPartitionIndex(node)); //move node G.setPartitionIndex(node, to); boundary.deleteNode(node, from, pair); EdgeWeight int_degree_node = 0; EdgeWeight ext_degree_node = 0; bool update_difficult = int_ext_degree(G, node, to, from, int_degree_node, ext_degree_node); if(ext_degree_node > 0) { boundary.insert(node, to, pair); } if(update_difficult) { boundary.postMovedBoundaryNodeUpdates(node, pair, true, false); } NodeWeight this_nodes_weight = G.getNodeWeight(node); (*from_part_weight) -= this_nodes_weight; (*to_part_weight) += this_nodes_weight; //update neighbors forall_out_edges(G, e, node) { NodeID target = G.getEdgeTarget(e); PartitionID targets_partition = G.getPartitionIndex(target); if((targets_partition != from && targets_partition != to)) { //at most difficult update nec. continue; //they dont need to be updated during this refinement } EdgeWeight int_degree = 0; EdgeWeight ext_degree = 0; PartitionID other_partition = targets_partition == from ? to : from; int_ext_degree(G, target, targets_partition, other_partition, int_degree, ext_degree); if(boundary.contains(target, targets_partition, pair)) { if(ext_degree == 0) { boundary.deleteNode(target, targets_partition, pair); } } else { if(ext_degree > 0) { boundary.insert(target, targets_partition, pair); } } } endfor
void two_way_fm::move_node(const PartitionConfig & config, graph_access & G, const NodeID & node, vertex_moved_hashtable & moved_idx, refinement_pq * from_queue, refinement_pq * to_queue, PartitionID from, PartitionID to, boundary_pair * pair, NodeWeight * from_part_weight, NodeWeight * to_part_weight, complete_boundary & boundary) { //move node G.setPartitionIndex(node, to); boundary.deleteNode(node, from, pair); EdgeWeight int_degree_node = 0; EdgeWeight ext_degree_node = 0; bool difficult_update = int_ext_degree(G, node, to, from, int_degree_node, ext_degree_node); if(ext_degree_node > 0) { boundary.insert(node, to, pair); } if(difficult_update) boundary.postMovedBoundaryNodeUpdates(node, pair, true, false); NodeWeight this_nodes_weight = G.getNodeWeight(node); (*from_part_weight) -= this_nodes_weight; (*to_part_weight) += this_nodes_weight; //update neighbors forall_out_edges(G, e, node) { NodeID target = G.getEdgeTarget(e); PartitionID targets_partition = G.getPartitionIndex(target); if((targets_partition != from && targets_partition != to)) { continue; } EdgeWeight int_degree = 0; EdgeWeight ext_degree = 0; PartitionID other_partition = targets_partition == from ? to : from; int_ext_degree(G, target, targets_partition, other_partition, int_degree, ext_degree); refinement_pq * queue_to_update = 0; if(targets_partition == from) { queue_to_update = from_queue; } else { queue_to_update = to_queue; } Gain gain = ext_degree - int_degree; if(queue_to_update->contains(target)) { if(ext_degree == 0) { queue_to_update->deleteNode(target); boundary.deleteNode(target, targets_partition, pair); } else { queue_to_update->changeKey(target, gain); } } else { if(ext_degree > 0) { if(moved_idx[target].index == NOT_MOVED) { queue_to_update->insert(target, gain); } boundary.insert(target, targets_partition, pair); } else { boundary.deleteNode(target, targets_partition, pair); } } } endfor