예제 #1
0
파일: util.cpp 프로젝트: mapleyustat/papaya
bool Boundary::contour_is_complete (contour_iterator cit) const
{
    edge_iterator eit = edges_begin (cit);
    edge_iterator end = edges_end (cit);
    for (; eit != end; ++eit)
        if (!edge_has_successor (eit))
            return false;
    return true;
}
예제 #2
0
파일: util.cpp 프로젝트: mapleyustat/papaya
void Boundary::reverse_contour (Boundary::contour_iterator cit) {
    edge_iterator eit     = edges_begin (cit);
    edge_iterator eit_end = edges_end (cit);
    for (; eit != eit_end; ++eit) {
        edge_t &E = edge (eit);
        std::swap (E.prev, E.next);
        std::swap (E.vert0, E.vert1);
    }
}
예제 #3
0
파일: util.cpp 프로젝트: mapleyustat/papaya
void Boundary::fix_contours (bool silent) {
    assert_boundary (*this);
    if (!silent)
        std::cerr << "fix_contours";
    int deg_edges = 0;
    int deg_spikes = 0;
    std::vector <int> deg_con_indices;
    Boundary::contour_iterator cit = contours_begin ();
    Boundary::contour_iterator cit_end = contours_end ();
    Boundary::edge_iterator eit, eit_end;
    while (cit != cit_end) {
        bool fixed_something = false;
        eit = edges_begin (cit);
        eit_end = edges_end (cit);
        // remove spikes with exterior angle = pi
        while (eit != eit_end) {
            edge_iterator eit_next = eit;
            ++eit_next;

            vec_t d = edge_vertex1 (eit_next);
            d -= edge_vertex0 (eit);

            if (d.norm () < VERTEX_MERGE_TOLERANCE) {
                if (is_self_referential (eit)) {
                    // further processing is dangerous
                    goto deg_contour;
                }
                // remove spike.  the norm-zero edge created by this
                // operation is removed later
                eit = remove_vertex1 (eit);
                ++deg_spikes;
                --eit;
                // remove_vertex1 could have removed our end
                eit_end = edges_end (cit);
                fixed_something = true;
            } else {
                eit = eit_next;
            }
        }
        eit = edges_begin (cit);
        // remove norm-zero edges
        while (eit != eit_end) {
            double len = edge_length (eit);
            if (len < VERTEX_MERGE_TOLERANCE) {
                if (is_self_referential (eit)) {
                    // further processing is dangerous
                    goto deg_contour;
                }
                ++deg_edges;
                eit = remove_vertex1 (eit);
                // remove_vertex1 could have removed our end
                eit_end = edges_end (cit);
                fixed_something = true;
            } else {
                ++eit;
            }
        }

        if (!fixed_something)
            ++cit;
        continue;

    deg_contour:
        // current contour has been reduced to or was a single-vertex
        // contour.  we mark it for later removal.
        deg_con_indices.push_back (cit - contours_begin ());
        ++cit;
    }
    int deg_contours = (int)deg_con_indices.size ();
    // remove degenerate contours
    {
        std::vector <int>::reverse_iterator it;
        it = deg_con_indices.rbegin ();
        for (; it != deg_con_indices.rend (); ++it) {
            erase_contour_by_index (*it);
        }
    }

    // final "status report"
    if (!silent) {
        std::cerr << "\n"
                  << std::setw (4) << deg_contours << " deg. contours (removed)\n"
                  << std::setw (4) << deg_spikes << " deg. spikes (removed)\n"
                  << std::setw (4) << deg_edges << " deg. edges (removed)\n";
    }
    assert_boundary (*this);
}
예제 #4
0
struct Edge* find_MST_parallel_star(Graph g){
    omp_set_num_threads(THREADS);
    int n = get_num_nodes(g);
    //store the edge index of the min weight edge incident on node i
    struct Edge* min_edges = new struct Edge[n];
    struct set *components = new struct set[n];

    struct Edge* mst_edges = new struct Edge[n];

    bool *coin_flips = new bool[n];
    //bool not_one_component = true;
    //keeps track of which tails have been contracted
    bool *is_contracted = new bool[n];
    
    //bool not_one_component = true;

    //this is a hacky way to accommodate the fact that we look at every edge
    //even though we're contracting
    bool is_first_passes[n];
    //loop guard - did the graph get smaller - only needs to be set by
    //at least one thread so it should work in the parallel version
    bool can_be_contracted = true;

    #pragma omp parallel for schedule(static)
    for(int i = 0; i < n; i++){
        components[i].parent = i;
        components[i].rank = 0;
        is_first_passes[i] = true;
    }

    double startTimeFind, endTimeFind;
    double findTotal = 0.0;
    double startTimeContract, endTimeContract;
    double contractTotal = 0.0;
    //continue looping until there's only 1 component
    //in the case of a disconnected graph, until num_components doesn't change
    //TODO is it better to have one condition here and not have to deal with
    //not_one_component (you would go one extra iteration but it could be worth 
    //it instad of having to loop through the components list every iteration -
    //but one iteration could be just as expensive so we'll have to see)
    while(can_be_contracted){
        startTimeFind = CycleTimer::currentSeconds();
        #pragma omp parallel for schedule(dynamic, CHUNKSIZE)
        for(int j = 0; j < n; j++){
            if(find_parallel(components, j) == j){
            //find minimum weight edge out of each componenet
                for(int i = 0; i < n; i++){
                    int set1 = find_parallel(components, i);
                    if(set1 == j){
                        const Vertex* start = edges_begin(g, i);
                        const Vertex* end = edges_end(g, i);
                        int weight_offset = -1;
                        for(const Vertex* v = start; v < end; v++){
                            weight_offset++;
                            //get representative nodes 
                            int set2 = find_parallel(components, *v);
                            //this edge has already been contracted (endpoints in same component)
                            if(set1 != set2){
                                Edge e;
                                e.src = i;
                                e.dest = *v;
                                e.weight = g->weights[g->offsets[i] + weight_offset];
                                if(is_first_passes[set1]){
                                    min_edges[set1] = e; 
                                    is_first_passes[set1] = false;
                                }
                                else if (min_edges[set1].weight > e.weight)
                                    min_edges[set1] = e;
                            }
                        }
                    }
                }
            }
        }

        endTimeFind = CycleTimer::currentSeconds();
        findTotal += (endTimeFind - startTimeFind);

        startTimeContract = CycleTimer::currentSeconds();
        //TODO: need to rewrite union find so that it always contract the edge that we want
        //it to - this is necessary in star contraction so we contract into the HEAD        
        //determine which vertices will be star centers and which are satellites
        //we make 0 mean you are a satellite (false) and 1 mean you are a star center (true)
        #pragma omp parallel for schedule(static)
        for(int i = 0; i < n; i++){
            coin_flips[i] = ((rand() % 2) == 1);
        }

        //do this so we can see if any thread sets to true meaning something got contracted
        can_be_contracted = false;
        //star contraction - we'll say 1 is HEADS and 0 is TAILS
        #pragma omp parallel for schedule(dynamic, CHUNKSIZE) 
        for(int i = 0; i < n; i++){
            int src = min_edges[i].src;
            int dest = min_edges[i].dest;

            int root1 = find_parallel(components, src);
            int root2 = find_parallel(components, dest);
            if(root1 == root2){
                continue;
            }
            can_be_contracted = true;
            //you wouldn't contract in case of both heads or both tails
            if((coin_flips[root1] == coin_flips[root2])){
                continue;
            }
            //try to contract, but if you fail, that means someone has contracted already
            //I think this should be correct by how CAS works
            //mark the tail as having been contracted
            if(coin_flips[root1]){
                if(!__sync_bool_compare_and_swap(&is_contracted[root2],false,true))
                    continue;
            }
            else{
                if(!__sync_bool_compare_and_swap(&is_contracted[root1],false,true))
                    continue;
            }
            if(coin_flips[root1]){
                union_parallel(components, root2, root1);
                mst_edges[root2] = min_edges[i];
            }
            else{
                union_parallel(components, root1, root2);
                mst_edges[root1] = min_edges[i];
            }
        }

        #pragma omp parallel for schedule(static)
        for(int i = 0; i < n; i++){
            is_first_passes[i] = true;
            is_contracted[i] = false;
        }
        endTimeContract = CycleTimer::currentSeconds();
        contractTotal += (endTimeContract - startTimeContract);
    }

/*    for(int i = 0; i < n; i++){
        if(mst_edges[i].src == 0 && mst_edges[i].dest == 0)
            continue;
        if(mst_edges[i].src < 0 || mst_edges[i].src > n || mst_edges[i].dest < 0 || mst_edges[i].dest > n)
            continue;
        printf("%d, %d\n", mst_edges[i].src, mst_edges[i].dest);
    }
  */  
    printf("find time parallel comp star: %.20f\n", findTotal);
    printf("contract time parallel comp star: %.20f\n", contractTotal);
    delete[] min_edges;
    delete[] components;
    return mst_edges;
}