Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

kconnected.cc

00001 //TODO: Toleranzen und EPS bestimmen, MIN_CUT braucht int-Gewichte!
00002 
00003 #ifndef SCIL_KCONNECTED_CC
00004 #define SCIL_KCONNECTED_CC
00005 
00006 #define LEPS 1e-4
00007 #define UEPS 1e4
00008 
00009 using namespace boost;
00010 using namespace SCIL;
00011 using namespace std;
00012 
00013 template <typename Graph>
00014 KCONNECTED<Graph>::KCONNECTED(Graph& G_, var_map<edge_descriptor>& VM_, int k_)
00015    : G(G_), VM(VM_), k(k_) {
00016    edge_descriptor e;
00017    feps = 1.0e-4;
00018    BGL_FORALL_EDGES_T(e, G, Graph)
00019       if(VM[e].type() != Vartype_Binary) {
00020          cerr << "kconnected.cc: All variables in VM need to be";
00021          cerr << " Vartype_Binary" << endl;
00022          exit(1);
00023       }
00024    //Graph has to provides edges() and vertices()
00025    BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00026    //Graph has to provide out_edges()
00027    BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<Graph>));
00028 }
00029 
00030 template <typename Graph>
00031 void KCONNECTED<Graph>::init(subproblem& S) {
00032    if (S.configuration("KCONNECTED_Debug_Out")=="true")
00033       cerr << "KCONNECTED::init\n";
00034    //Check whether Graph is undirected
00035    typedef typename GraphTraits::directed_category directed_category;
00036    if (!(is_same<directed_category,undirected_tag>::value
00037          || is_base_and_derived<undirected_tag, directed_category>::value)) {
00038       cerr << "kconnected.cc: The graph has to be undirected." << endl;
00039       exit(1);
00040    };
00041 
00042    //Check for parallel edges
00043    map<vertex_descriptor, map<vertex_descriptor, int> > edge_count;
00044    BGL_FORALL_EDGES_T(e, G, Graph)
00045       edge_count[source(e, G)][target(e, G)] = 0;
00046    BGL_FORALL_EDGES_T(e, G, Graph) {
00047       edge_count[source(e, G)][target(e, G)]++;
00048       edge_count[target(e, G)][source(e, G)]++;
00049       if (edge_count[source(e, G)][target(e, G)] > 1) {
00050          cerr << "kconnected.cc: The graph should not contain parallel edges.";
00051          cerr << endl;
00052          exit(1);
00053       }
00054    }
00055    BGL_FORALL_VERTICES_T(v, G, Graph) {
00056       row r;
00057       typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00058       for(tie(oe_it, oe_it_end)=out_edges(v, G); oe_it != oe_it_end; oe_it++)
00059          r += VM[*oe_it];
00060       if(r.size() > 0 )
00061          S.add_basic_constraint(r>=k, Static);
00062    }
00063    return;
00064 };
00065 
00066 template <typename Graph>
00067 typename KCONNECTED<Graph>::status KCONNECTED<Graph>::feasible(solution& S) {
00068    if (S.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00069       cerr << "KCONNECTED::feasible\n";
00070    map<edge_descriptor, int> w;
00071 
00072    BGL_FORALL_EDGES_T(e, G, Graph) {
00073       w[e] = int(double(UEPS) * S.value(VM[e]));
00074       if( w[e] < 0 )
00075                w[e] = 0;
00076    }
00077 
00078    MIN_CUT<Graph> *min_cut = new MIN_CUT<Graph>(G, w);
00079    int cv = (min_cut->run())->first;
00080    if( cv < k * UEPS )
00081       return infeasible_solution;
00082    else
00083       return feasible_solution;
00084 }
00085 
00086 template <typename Graph>
00087 int KCONNECTED<Graph>::cutTreeSeparation(solution& sol, 
00088                                          list<cons_obj*>& newCons) {
00089    if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00090       cerr << "KCONNECTED::cutTreeSeparation\n";
00091 
00092    int numfound = 0;
00093    map<edge_descriptor, double> ctc;
00094    map<vertex_descriptor, vertex_descriptor> p;
00095    map<vertex_descriptor, double> fl;
00096    BGL_FORALL_VERTICES_T(v, G, Graph) {
00097       p[v] = 0;
00098       fl[v] = -1.;
00099    }
00100    BGL_FORALL_EDGES_T(b, G, Graph) {
00101       ctc[b] = sol.value(VM[b]);
00102       if( ctc[b] < 1e-4 )
00103                ctc[b] = 1e-4;
00104    }
00105    computeCutTree(G, ctc, p, fl);
00106 
00107    BGL_FORALL_VERTICES_T(v, G, Graph) {
00108       if( p[v] == v || fl[v] >= double(k) - .0001 )
00109                continue;
00110       if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00111          cerr << "fl: " << fl[v] << endl;
00112       row s;
00113       int rt = 0;
00114 
00115       //temporarily delete one edge of the cut tree
00116       vertex_descriptor ov = p[v];
00117       p[v] = v;
00118 
00119       //determine the cut nodes
00120       typedef map<vertex_descriptor, set<vertex_descriptor>* > vertex_partition;
00121       vertex_partition vpartition;
00122       //Initialize the vertex_partition
00123       BGL_FORALL_VERTICES_T(w, G, Graph) {
00124          vpartition[w] = new set<vertex_descriptor>();
00125          vpartition[w]->insert(w);
00126       }
00127 
00128       //Store the number of blocks in the Partition
00129       int num_blocks = num_vertices(G);
00130       //Union sets of vertices w with sets of vertices p[w]
00131       BGL_FORALL_VERTICES_T(w, G, Graph) {
00132          set<vertex_descriptor> *tmp = vpartition[p[w]];
00133          vpartition[w]->insert(tmp->begin(), tmp->end());
00134          typename set<vertex_descriptor>::iterator it;
00135          //Update the pointers of the vertices in vpartition[p[w]]
00136          for(it = tmp->begin(); it != tmp->end(); it++)
00137             vpartition[*it] = vpartition[w];
00138          num_blocks--;
00139       }
00140 
00141       if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00142          cerr << "blocks: " << num_blocks << endl;
00143       BGL_FORALL_EDGES_T(f, G, Graph) {
00144          // Check whether source and target of edge f are in the same block
00145          if( *(vpartition[source(f, G)]) == *(vpartition[target(f, G)] ))
00146             s += VM[f];
00147       }
00148       newCons.push_back(s>=double(k));
00149       if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00150          cerr << s << endl;
00151       numfound++;
00152       p[v] = ov;
00153    }
00154    return numfound;
00155 }
00156 
00157 template<typename Graph>
00158 typename KCONNECTED<Graph>::status KCONNECTED<Graph>::standard_separation(subproblem& S) {
00159    if (S.configuration("KCONNECTED_Debug_Out")=="true")
00160       cerr << "KCONNECTED::standard_separation\n";
00161    solution sol;
00162    sol.save_solution(S);
00163    list<cons_obj*> newCons;
00164    bool found = false;
00165 
00166    if( cutTreeSeparation(sol, newCons) ) {
00167       //if( separateCut(sol, newCons) ) {
00168       list<cons_obj*>::const_iterator c;
00169       for(c = newCons.begin(); c != newCons.end(); c++) {
00170          if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00171             cerr << "vio: " << (*c)->violation(S) << endl;
00172          if( (*c)->violation(S) > feps ) {
00173             S.add_basic_constraint(*c);
00174             found = true;
00175          }
00176          else
00177             delete *c;
00178       }
00179       // exit(1);
00180    }
00181    if( found )
00182       return constraint_found;
00183 
00184    return no_constraint_found;
00185 }
00186 
00187 template <typename Graph>
00188 void KCONNECTED<Graph>::info() {
00189    cout<<"Configurations:\n";
00190    cout<<"KCONNECTED_Debug_Out [true|false]\n";
00191 };
00192 #endif
Generated on Mon Mar 28 22:03:48 2011 for SCIL by  doxygen 1.6.3