Program Listing for File graph_constructors.cpp

Return to documentation for file (src/graph_constructors.cpp)

#include <iostream>
#include "graph_constructors.hpp"

bool graspi::build_graph(const std::string& name,
                         graph_t*& G,
                         dim_g_t& d_g,
                         vertex_colors_t& C,
                         edge_weights_t& W,
                         edge_colors_t& L) {
    std::ifstream f(name.c_str());
    if (!f) return false;
    return build_graph(f, G, d_g, C, W, L);
} // build_graph


bool graspi::build_graph(graph_t*& G, const dim_g_t& d_g,
                         vertex_colors_t& C, dim_a_t& d_a,
                         edge_weights_t& W,
                         edge_colors_t& L,
                         double pixelsize, bool if_per_on_size);

void graspi::initlize_colors_meta_vertices( vertex_colors_t& C, const dim_g_t& d_g ){

    //    std::cerr << "Test: " << C.size() << " " << d_g.n_bulk << std::endl;

    C[d_g.n_bulk]   = BLUE;  // bottom electrode
    C[d_g.n_bulk+1] = RED;   // top electrode
    C[d_g.n_bulk+2] = GREEN; // meta vertex - I D/A
    if(d_g.n_phases == 3){
        C[d_g.n_bulk+3] = DGREEN; // meta vertex - I D/D+A
        C[d_g.n_bulk+4] = LGREEN; // meta vertex - I A/D+A
    }
}

template <typename Container>
bool graspi::update_graph(const Container& M, const dim_a_t& d,
                          graph_t& G, dim_g_t& d_g,
                          vertex_colors_t& C,
                          edge_weights_t& W,
                          edge_colors_t& L) {
    // no error checking
    C.resize( M.size()+d_g.n_meta() );
    for (unsigned int i = 0; i < M.size(); ++i) C[i] = M[i];

    //      initlize_color_meta_vertices( C, d_g );
    return true;
} // update_graph


/*
 * Function adds/updates edges to the graph
 * between interface meta-vertex and bulk vertices
 * with corresponding attributes
 * s      - source vertex to be checked
 * meta_t - meta vertex to which edge is linked
 * w,o    - attributes of new edges
 */

bool graspi::build_graph(std::istream& is,
                         graph_t*& G,
                         dim_g_t& d_g,
                         vertex_colors_t& C,
                         edge_weights_t& W,
                         edge_colors_t& L){

    // n is size of graphe w/o special vertices
    unsigned int n = 0;

    if(!is) {
        std::cerr << "Problem with istream!" << std::endl;
        return false;
    }

    int n_of_vertices = 1;
    int green_vertex, lgreen_vertex, dgreen_vertex;

    int i=0;
    do {
        std::string tmp;
        getline(is,tmp);
        std::istringstream iss(tmp);
        if(!is) {
            std::cerr << "Problem with input file - line " << i << std::endl;
            delete G;
            return false;
        }

        if(i==0){
            iss >> n_of_vertices;
            n = n_of_vertices;
            d_g.n_bulk = n_of_vertices;
            G = new graspi::graph_t( d_g.n_total() );
            C.resize(d_g.n_total(), 13);
            initlize_colors_meta_vertices(C,d_g);
            green_vertex = d_g.n_bulk+2;
            if(d_g.n_phases == 3){
                dgreen_vertex = d_g.n_bulk+3;
                lgreen_vertex = d_g.n_bulk+4;
            }
        }

        if( (i>0) && ( i <= n_of_vertices ) ){
            int s = 0;
            iss >> s;
            iss >> C[s];
            int t = 0;
            double w = 0.0;
            char o;
            do{
                iss >> t;
                iss >> w;
                iss >> o;

                if(!iss ) break;

                if (t == -3) continue;
                if (t < 0) {
                    t = n-t-1;
                    w = 0;
                    o = 's';
                }
                add_edge_to_graph(s, t, o, w,
                                  green_vertex, dgreen_vertex, lgreen_vertex,
                                  G,C,W,L);

            }while(iss);

        }

        if( i > n_of_vertices ){
            int s = 0;
            iss >> s;
            iss >> C[s];
            int t = 0;
            double w = 0.0;
            char o;
            do{
                iss >> t;
                iss >> w;
                iss >> o;

                if(!iss ) break;

                if (t == -3) continue;
                if (t < 0) {
                    t = n-t-1;
                    w = 0;
                    o = 's';
                }
                add_edge_to_graph(s, t, o, w,
                                  green_vertex, dgreen_vertex, lgreen_vertex,
                                  G,C,W,L);
            }while(iss);
        }
        if (i >= (n_of_vertices+2) ) break;
        i++;
    }while(is);


    return true;
}//build_graph



bool graspi::build_graph(graph_t*& G, const dim_g_t& d_g,
                         vertex_colors_t& C, dim_a_t& d_a,
                         edge_weights_t& W,
                         edge_colors_t& L,
                         double pixelsize, bool if_per_on_size
                         ) {

    G = new graspi::graph_t( d_g.n_total() );
    int n = d_g.n_bulk;
#ifdef DEBUG
    std::cout << "n: " << n << std::endl;
#endif

    if(d_a.nz == 0) d_a.nz = 1;
    initlize_colors_meta_vertices( C, d_g );
    int green_vertex, lgreen_vertex, dgreen_vertex;
    green_vertex = d_g.n_bulk+2;
    if(d_g.n_phases == 3){
        dgreen_vertex = d_g.n_bulk+3;
        lgreen_vertex = d_g.n_bulk+4;
    }

    int ngbr_size = 8;
    if(d_a.nz > 1) ngbr_size = 26;
    std::pair<int,char>* ngbr = new std::pair<int,char> [ngbr_size];

    for(unsigned int k = 0; k < d_a.nz; k++){
        for(unsigned int j = 0; j < d_a.ny; j++){
            for(unsigned int i = 0; i < d_a.nx; i++){
                generate_ngbr(i,j,k,d_a,ngbr,if_per_on_size);

                int id = i + d_a.nx * ( j + d_a.ny * k );
                int s = id;
                for (int i_ngbr=0; i_ngbr < ngbr_size; i_ngbr++){
                    int t = ngbr[i_ngbr].first;
                    char o = ngbr[i_ngbr].second;
                    double w = 1.0 * pixelsize;
                    if( o == 's') w = sqrt(2.0) * pixelsize;
                    if( o == 't') w = sqrt(3.0) * pixelsize;

                    if (t == -3) continue;
                    // for metavertices corresponding to electrode correct indices
                    // old: cathode has index:-1 in the inputdata
                    // new: cathode has index: n_bulk+1 (appended at the end)
                    // similar operation applied to anode
                    // anode has index : n_bulk+2
                    if (t < 0){
                        t = n-t-1;
                        o = 's';
                        w = 0.0;
                    }
#ifdef DEBUG
                    std::cerr << "( " << s << "," << t << " )"
                    << o << " " << w << " , "
                    << C[s] << " " << C[t] << std::endl;
#endif
                    add_edge_to_graph(s, t, o, w,
                                      green_vertex,
                                      dgreen_vertex,
                                      lgreen_vertex,
                                      G,C,W,L);
                }
            }//i
        }//j
    }//k

    delete[] ngbr;

    return true;
} // build_graph


void graspi::add_edge_to_graph(int s, int t, char o, double w,
                               int green_vertex,
                               int dgreen_vertex,
                               int lgreen_vertex,
                               graph_t* G,
                               vertex_colors_t& C,
                               edge_weights_t& W,
                               edge_colors_t& L) {

    graspi::edge_descriptor_t e;
    bool e_res = false;

    boost::tie(e, e_res) = boost::edge(s, t, *G);
    if (e_res == false) {
        boost::tie(e, e_res) = boost::add_edge(s, t, *G);
        std::pair<int,int> p = std::pair<int,int>(std::min(s,t),
                                                  std::max(s,t));
        W[e] = w;
        L[p] = o;
    }

    if(C[s]+C[t] == 1){
        //add edge between white and green
        make_update_edge_with_meta_vertex( s, green_vertex,
                                          w, o, G, W, L);
        //add edge between black and green
        make_update_edge_with_meta_vertex( t, green_vertex,
                                          w, o, G, W, L);
    }//I D/A

    if(C[s]+C[t] == 3){
        //add edge between black and dgreen
        make_update_edge_with_meta_vertex( s, dgreen_vertex,
                                          w, o, G, W, L);
        //add edge between grey and green
        make_update_edge_with_meta_vertex( t, dgreen_vertex,
                                          w, o, G, W, L);
    }//I D/D+A

    if(C[s]+C[t] == 4){
        //add edge between white and lgreen
        make_update_edge_with_meta_vertex( s, lgreen_vertex,
                                          w, o, G, W, L);
        //add edge between grey and lgreen
        make_update_edge_with_meta_vertex( t, lgreen_vertex,
                                          w, o, G, W, L);
    }//I A/D+A
}

void graspi::make_update_edge_with_meta_vertex( int s, int meta_t,
                                               double w, char o,
                                               graph_t* G,
                                               edge_weights_t& W,
                                               edge_colors_t& L)
{

    //add edges between source and target_metavertex
    graspi::edge_descriptor_t e;
    bool e_res = false;
    boost::tie(e, e_res) = boost::edge(s, meta_t, *G);
    if (e_res == false) {
        std::pair<int,int> p = std::pair<int,int>(std::min(s,meta_t),
                                                  std::max(s,meta_t));
        boost::tie(e, e_res) = boost::add_edge(s, meta_t, *G);
        W[e] = w/2.0;
        L[p]=o;
    }else{ // if edge exist check if current distance is shorter
        // and change accordingly
        float existing_distance = boost::get(W, e);
        if( (w/2.0) < existing_distance){
            std::pair<int,int> p = std::pair<int,int>(std::min(s,meta_t),
                                                      std::max(s,meta_t));
            W[e] = w/2.0;
            L[p] = o;
        }
    }
}


// determine the position in row-wise array on the basis of index i_x and i_y
int graspi::compute_pos_2D(int i_x, int i_y,
                           const dim_a_t& d_a,
                           bool if_per_on_sides){

    if( i_y == -1)    return -1;
    if( i_y == d_a.ny )  return -2;

    if (if_per_on_sides){
        if ( i_x == -1 )     i_x = d_a.nx-1;
        if ( i_x == d_a.nx ) i_x = 0;
    }else{
        if( ( i_x == -1 ) || (i_x == d_a.nx) ) return -3;
    }

    return i_x + d_a.nx * i_y ;
}


// determine the position in row-wise array on the basis of index i_x and i_y
int graspi::compute_pos_3D(int i_x, int i_y, int i_z,
                           const dim_a_t& d_a,
                           bool if_per_on_sides){

    if( i_z == -1)    return -1;
    if( i_z == d_a.nz )  return -2;

    if (if_per_on_sides){
        if ( i_x == -1 )     i_x = d_a.nx-1;
        if ( i_x == d_a.nx ) i_x = 0;
        if ( i_y == -1 )     i_y = d_a.ny-1;
        if ( i_y == d_a.ny ) i_y = 0;
    }else{
        if(
           ( i_x == -1 ) || ( i_x == d_a.nx )
           ||
           ( i_y == -1 ) || ( i_y == d_a.ny )
           )
            return -3;
    }

    return i_x + d_a.nx * (i_y + d_a.ny * i_z) ;
}


// generate 2D neighborhood for 2D case
void graspi::generate_ngbr(int i, int j, int k,
                           const dim_a_t& d_a,
                           std::pair<int,char>* ngbr,
                           bool if_per_on_sides ){
    // 2D
    if( (d_a.nz == 0) || (d_a.nz == 1) ) {
        k = 0;
        ngbr[0].first = compute_pos_2D(i  ,j+1, d_a, if_per_on_sides);  // ngbr N
        ngbr[1].first = compute_pos_2D(i+1,j+1, d_a, if_per_on_sides);  // ngbr NE
        ngbr[2].first = compute_pos_2D(i+1,j  , d_a, if_per_on_sides);  // ngbr E
        ngbr[3].first = compute_pos_2D(i+1,j-1, d_a, if_per_on_sides);  // ngbr ES
        ngbr[4].first = compute_pos_2D(i  ,j-1, d_a, if_per_on_sides);  // ngbr S
        ngbr[5].first = compute_pos_2D(i-1,j-1, d_a, if_per_on_sides);  // ngbr SW
        ngbr[6].first = compute_pos_2D(i-1,j  , d_a, if_per_on_sides);  // ngbr W
        ngbr[7].first = compute_pos_2D(i-1,j+1, d_a, if_per_on_sides);  // ngbr WN

        ngbr[0].second = 'f'; // ngbr N
        ngbr[1].second = 's'; // ngbr NE
        ngbr[2].second = 'f'; // ngbr E
        ngbr[3].second = 's'; // ngbr ES
        ngbr[4].second = 'f'; // ngbr S
        ngbr[5].second = 's'; // ngbr SW
        ngbr[6].second = 'f'; // ngbr W
        ngbr[7].second = 's'; // ngbr WN
    }else{// 3D
        ngbr[0].first = compute_pos_3D(i  ,j+1, k, d_a, if_per_on_sides);   // ngbr N
        ngbr[1].first = compute_pos_3D(i+1,j+1, k, d_a, if_per_on_sides);   // ngbr NE
        ngbr[2].first = compute_pos_3D(i+1,j  , k, d_a, if_per_on_sides);   // ngbr E
        ngbr[3].first = compute_pos_3D(i+1,j-1, k, d_a, if_per_on_sides);   // ngbr ES
        ngbr[4].first = compute_pos_3D(i  ,j-1, k, d_a, if_per_on_sides);   // ngbr S
        ngbr[5].first = compute_pos_3D(i-1,j-1, k, d_a, if_per_on_sides);   // ngbr SW
        ngbr[6].first = compute_pos_3D(i-1,j  , k, d_a, if_per_on_sides);   // ngbr W
        ngbr[7].first = compute_pos_3D(i-1,j+1, k, d_a, if_per_on_sides);   // ngbr WN

        ngbr[0].second = 'f'; // ngbr N
        ngbr[1].second = 's'; // ngbr NE
        ngbr[2].second = 'f'; // ngbr E
        ngbr[3].second = 's'; // ngbr ES
        ngbr[4].second = 'f'; // ngbr S
        ngbr[5].second = 's'; // ngbr SW
        ngbr[6].second = 'f'; // ngbr W
        ngbr[7].second = 's'; // ngbr WN

        ngbr[8].first  = compute_pos_3D(i  ,j+1, k+1, d_a, if_per_on_sides);    // ngbr N
        ngbr[9].first  = compute_pos_3D(i+1,j+1, k+1, d_a, if_per_on_sides);    // ngbr NE
        ngbr[10].first = compute_pos_3D(i+1,j  , k+1, d_a, if_per_on_sides);    // ngbr E
        ngbr[11].first = compute_pos_3D(i+1,j-1, k+1, d_a, if_per_on_sides);    // ngbr ES
        ngbr[12].first = compute_pos_3D(i  ,j-1, k+1, d_a, if_per_on_sides);    // ngbr S
        ngbr[13].first = compute_pos_3D(i-1,j-1, k+1, d_a, if_per_on_sides);    // ngbr SW
        ngbr[14].first = compute_pos_3D(i-1,j  , k+1, d_a, if_per_on_sides);    // ngbr W
        ngbr[15].first = compute_pos_3D(i-1,j+1, k+1, d_a, if_per_on_sides);    // ngbr WN
        ngbr[16].first = compute_pos_3D(i,j,     k+1, d_a, if_per_on_sides);    // ngbr WN

        ngbr[8].second  = 's'; // ngbr N
        ngbr[9].second  = 't'; // ngbr NE
        ngbr[10].second = 's'; // ngbr E
        ngbr[11].second = 't'; // ngbr ES
        ngbr[12].second = 's'; // ngbr S
        ngbr[13].second = 't'; // ngbr SW
        ngbr[14].second = 's'; // ngbr W
        ngbr[15].second = 't'; // ngbr WN
        ngbr[16].second = 'f'; // ngbr WN

        ngbr[17].first = compute_pos_3D(i  ,j+1, k-1, d_a, if_per_on_sides);    // ngbr N
        ngbr[18].first = compute_pos_3D(i+1,j+1, k-1, d_a, if_per_on_sides);    // ngbr NE
        ngbr[19].first = compute_pos_3D(i+1,j  , k-1, d_a, if_per_on_sides);    // ngbr E
        ngbr[20].first = compute_pos_3D(i+1,j-1, k-1, d_a, if_per_on_sides);    // ngbr ES
        ngbr[21].first = compute_pos_3D(i  ,j-1, k-1, d_a, if_per_on_sides);    // ngbr S
        ngbr[22].first = compute_pos_3D(i-1,j-1, k-1, d_a, if_per_on_sides);    // ngbr SW
        ngbr[23].first = compute_pos_3D(i-1,j  , k-1, d_a, if_per_on_sides);    // ngbr W
        ngbr[24].first = compute_pos_3D(i-1,j+1, k-1, d_a, if_per_on_sides);    // ngbr WN
        ngbr[25].first = compute_pos_3D(i,j,     k-1, d_a, if_per_on_sides);    // ngbr WN

        ngbr[17].second = 's'; // ngbr N
        ngbr[18].second = 't'; // ngbr NE
        ngbr[19].second = 's'; // ngbr E
        ngbr[20].second = 't'; // ngbr ES
        ngbr[21].second = 's'; // ngbr S
        ngbr[22].second = 't'; // ngbr SW
        ngbr[23].second = 's'; // ngbr W
        ngbr[24].second = 't'; // ngbr WN
        ngbr[25].second = 'f'; // ngbr WN

    }

}