multicut.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_MULTICUT_HXX
00003 #define OPENGM_MULTICUT_HXX
00004 
00005 #include <algorithm>
00006 #include <vector>
00007 #include <queue>
00008 #include <utility>
00009 #include <string>
00010 #include <iostream>
00011 #include <fstream>
00012 #include <typeinfo>
00013 #include <limits> 
00014 #ifndef WIDTH_BOOST
00015 #include <boost/unordered_map.hpp>
00016 #include <boost/unordered_set.hpp>     
00017 #else
00018 #include <ext/hash_map> 
00019 #include <ext/hash_set>
00020 #endif
00021 
00022 #include "opengm/datastructures/marray/marray.hxx"
00023 #include "opengm/opengm.hxx"
00024 #include "opengm/inference/inference.hxx"
00025 #include "opengm/inference/visitors/visitor.hxx" 
00026 #include "opengm/utilities/timer.hxx"
00027 
00028 #include <ilcplex/ilocplex.h>
00029 ILOSTLBEGIN
00030 
00031 namespace opengm {
00032 
00034 class HigherOrderTerm
00035 {
00036 public:
00037    size_t factorID_;
00038    bool   potts_;
00039    size_t valueIndex_;
00040    std::vector<size_t> lpIndices_;
00041    HigherOrderTerm(size_t factorID, bool  potts, size_t valueIndex) 
00042       : factorID_(factorID), potts_(potts),valueIndex_(valueIndex) {}
00043    HigherOrderTerm() 
00044       : factorID_(0), potts_(false),valueIndex_(0) {}           
00045 };
00047 
00066 template<class GM, class ACC>
00067 class Multicut : public Inference<GM, ACC>
00068 {
00069 public:
00070    typedef ACC AccumulationType;
00071    typedef GM GraphicalModelType;
00072    OPENGM_GM_TYPE_TYPEDEFS;
00073    typedef size_t LPIndexType;
00074    typedef VerboseVisitor<Multicut<GM,ACC> > VerboseVisitorType;
00075    typedef EmptyVisitor<Multicut<GM,ACC> > EmptyVisitorType;
00076    typedef TimingVisitor<Multicut<GM,ACC> > TimingVisitorType;
00077 
00078 
00079 #ifndef WIDTH_BOOST 
00080    typedef  boost::unordered_map<IndexType, LPIndexType> EdgeMapType;
00081    typedef  boost::unordered_set<IndexType> MYSET; 
00082 #else 
00083    typedef __gnu_cxx::hash_map<IndexType, LPIndexType> EdgeMapType;
00084    typedef __gnu_cxx::hash_set<IndexType> MYSET; 
00085 #endif
00086 
00087 
00088    struct Parameter{
00089    public:
00090       enum MWCRounding {NEAREST,DERANDOMIZED,PSEUDODERANDOMIZED};
00091 
00092       int numThreads_;
00093       bool verbose_;
00094       bool verboseCPLEX_;
00095       double cutUp_;
00096       double timeOut_;
00097       std::string workFlow_;
00098       size_t maximalNumberOfConstraintsPerRound_;
00099       double edgeRoundingValue_;
00100       MWCRounding MWCRounding_;
00101       size_t reductionMode_;
00102 
00105       Parameter
00106       (
00107          int numThreads=0,
00108          double cutUp=1.0e+75
00109          )
00110          : numThreads_(numThreads), verbose_(false),verboseCPLEX_(false), cutUp_(cutUp),
00111            timeOut_(std::numeric_limits<double>::infinity()), maximalNumberOfConstraintsPerRound_(1000000),
00112            edgeRoundingValue_(0.00000001),MWCRounding_(NEAREST), reductionMode_(3)
00113          {};
00114    };
00115 
00116    virtual ~Multicut();
00117    Multicut(const GraphicalModelType&, Parameter para=Parameter());
00118    virtual std::string name() const {return "Multicut";}
00119    const GraphicalModelType& graphicalModel() const;
00120    virtual InferenceTermination infer();
00121    template<class VisitorType> InferenceTermination infer(VisitorType&);
00122    virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
00123    ValueType bound() const;
00124    ValueType value() const;
00125    ValueType calcBound(){ return 0; }
00126    ValueType evaluate(std::vector<LabelType>&) const;
00127 
00128    template<class LPVariableIndexIterator, class CoefficientIterator>
00129    void addConstraint(LPVariableIndexIterator, LPVariableIndexIterator,
00130                         CoefficientIterator, const ValueType&, const ValueType&);
00131    std::vector<double> getEdgeLabeling() const;
00132 
00133    size_t inferenceState_;
00134    size_t constraintCounter_;
00135 private:
00136    enum ProblemType {INVALID, MC, MWC};
00137 
00138    const GraphicalModelType& gm_; 
00139    ProblemType problemType_;
00140    Parameter parameter_;
00141    double constant_;
00142    double bound_;
00143    const double infinity_;
00144 
00145    LabelType   numberOfTerminals_;
00146    IndexType   numberOfNodes_;
00147    LPIndexType numberOfTerminalEdges_;
00148    LPIndexType numberOfInternalEdges_;
00149    LPIndexType terminalOffset_;
00150    LPIndexType numberOfHigherOrderValues_;
00151    LPIndexType numberOfInterTerminalEdges_;
00152 
00153    std::vector<std::vector<size_t> >               workFlow_;
00154    std::vector<std::pair<IndexType,IndexType> >    edgeNodes_;
00155 
00158    std::vector<EdgeMapType >   neighbours; 
00159 
00160    IloEnv         env_;
00161    IloModel       model_;
00162    IloNumVarArray x_;
00163    IloRangeArray  c_;
00164    IloObjective   obj_;
00165    IloNumArray    sol_;
00166    IloCplex       cplex_;
00167 
00168    bool           integerMode_;
00169    const double   EPS_;          //small number: for numerical issues constraints are still valid if the not up to EPS_
00170 
00171 
00172    void initCplex(); 
00173 
00174    size_t findCycleConstraints(IloRangeArray&, bool, bool);
00175    size_t findIntegerCycleConstraints(IloRangeArray&, bool);
00176    size_t findTerminalTriangleConstraints(IloRangeArray&);
00177    size_t findIntegerTerminalTriangleConstraints(IloRangeArray&, std::vector<LabelType>& conf);
00178    size_t findMultiTerminalConstraints(IloRangeArray&);
00179    size_t findOddWheelConstraints(IloRangeArray&);  
00180    size_t removeUnusedConstraints();            //TODO: implement
00181    size_t enforceIntegerConstraints();
00182 
00183    bool readWorkFlow(std::string);
00184   
00185    InferenceTermination partition(std::vector<LabelType>&, std::vector<std::list<size_t> >&, double) const;
00186    ProblemType setProblemType();
00187    LPIndexType getNeighborhood(const LPIndexType, std::vector<EdgeMapType >&,std::vector<std::pair<IndexType,IndexType> >&, std::vector<HigherOrderTerm>&);
00188 
00189    template <class DOUBLEVECTOR>
00190    double shortestPath(const IndexType, const IndexType, const std::vector<EdgeMapType >&, const DOUBLEVECTOR&, std::vector<IndexType>&, const double,bool) const;
00191 
00192    InferenceTermination derandomizedRounding(std::vector<LabelType>&) const;
00193    InferenceTermination pseudoDerandomizedRounding(std::vector<LabelType>&, size_t) const;
00194    double derandomizedRoundingSubProcedure(std::vector<LabelType>&,const std::vector<LabelType>&, const double) const;
00195 
00196    //PROTOCOLATION 
00197 
00198    enum{
00199       Protocol_ID_Solve              = 0,
00200       Protocol_ID_AddConstraints     = 1,
00201       Protocol_ID_RemoveConstraints  = 2,
00202       Protocol_ID_IntegerConstraints = 3,
00203       Protocol_ID_CC                 = 4, 
00204       Protocol_ID_TTC                = 5,
00205       Protocol_ID_MTC                = 6,
00206       Protocol_ID_OWC                = 7,
00207       Protocol_ID_Unknown            = 8  
00208    };
00209    
00210    enum{
00211       Action_ID_RemoveConstraints  = 0,
00212       Action_ID_IntegerConstraints = 1,
00213       Action_ID_CC                 = 10, 
00214       Action_ID_CC_I               = 11, 
00215       Action_ID_CC_IFD             = 12, 
00216       Action_ID_CC_FD              = 13, 
00217       Action_ID_CC_B               = 14, 
00218       Action_ID_CC_FDB             = 15, 
00219       Action_ID_TTC                = 20,    
00220       Action_ID_TTC_I              = 21,   
00221       Action_ID_MTC                = 30,    
00222       Action_ID_OWC                = 40
00223    };    
00224    
00225    std::vector<std::vector<double> > protocolateTiming_;
00226    std::vector<std::vector<size_t> > protocolateConstraints_;
00227  
00228 };
00229  
00230 template<class GM, class ACC>
00231 typename Multicut<GM, ACC>::LPIndexType Multicut<GM, ACC>::getNeighborhood
00232 (
00233    const LPIndexType numberOfTerminalEdges,
00234    std::vector<EdgeMapType >& neighbours,
00235    std::vector<std::pair<IndexType,IndexType> >& edgeNodes,
00236    std::vector<HigherOrderTerm>& higherOrderTerms
00237    )
00238 {
00239    //Calculate Neighbourhood
00240    neighbours.resize(gm_.numberOfVariables());
00241    LPIndexType numberOfInternalEdges=0;
00242    LPIndexType numberOfAdditionalInternalEdges=0;
00243    // Add edges that have to be included
00244    for(size_t f=0; f<gm_.numberOfFactors(); ++f) {
00245       if(gm_[f].numberOfVariables()==2) { // Second Order Potts
00246          IndexType u = gm_[f].variableIndex(1);
00247          IndexType v = gm_[f].variableIndex(0);
00248          if(neighbours[u].find(v)==neighbours[u].end()) {
00249             neighbours[u][v] = numberOfTerminalEdges+numberOfInternalEdges;
00250             neighbours[v][u] = numberOfTerminalEdges+numberOfInternalEdges;
00251             edgeNodes.push_back(std::pair<IndexType,IndexType>(v,u));     
00252             ++numberOfInternalEdges;
00253          }
00254       }
00255    }
00256    for(size_t f=0; f<gm_.numberOfFactors(); ++f) {
00257       if(gm_[f].numberOfVariables()>2 && !gm_[f].isPotts()){ // Generalized Potts
00258          higherOrderTerms.push_back(HigherOrderTerm(f, false, 0));      
00259          for(size_t i=0; i<gm_[f].numberOfVariables();++i) {
00260             for(size_t j=0; j<i;++j) {
00261                IndexType u = gm_[f].variableIndex(i);
00262                IndexType v = gm_[f].variableIndex(j);
00263                if(neighbours[u].find(v)==neighbours[u].end()) {
00264                   neighbours[u][v] = numberOfTerminalEdges+numberOfInternalEdges;
00265                   neighbours[v][u] = numberOfTerminalEdges+numberOfInternalEdges;
00266                   edgeNodes.push_back(std::pair<IndexType,IndexType>(v,u));     
00267                   ++numberOfInternalEdges;
00268                   ++numberOfAdditionalInternalEdges;
00269                }
00270             }
00271          }
00272       }
00273    }
00274    //Add for higher order potts term only neccesary edges 
00275    for(size_t f=0; f<gm_.numberOfFactors(); ++f) {
00276       if(gm_[f].numberOfVariables()>2 && gm_[f].isPotts()) { //Higher order Potts
00277          higherOrderTerms.push_back(HigherOrderTerm(f, true, 0));  
00278          std::vector<LPIndexType> lpIndexVector;
00279          //Find spanning tree vor the variables nb(f) using edges that already exist.
00280          std::vector<bool> variableInSpanningTree(gm_.numberOfVariables(),true);
00281          for(size_t i=0; i<gm_[f].numberOfVariables();++i) {
00282             variableInSpanningTree[gm_[f].variableIndex(i)]=false;
00283          }     
00284          size_t connection = 2; 
00285          // 1 = find a spanning tree and connect higher order auxilary variable to this
00286          // 2 = find a spanning subgraph including at least all eges in the subset and connect higher order auxilary variable to this
00287          if(connection==2){
00288             // ADD ALL 
00289             for(size_t i=0; i<gm_[f].numberOfVariables();++i) {
00290                const IndexType u = gm_[f].variableIndex(i);  
00291                for(typename EdgeMapType::const_iterator it=neighbours[u].begin() ; it != neighbours[u].end(); ++it){
00292                   const IndexType v = (*it).first;
00293                   if(variableInSpanningTree[v] == false && u<v){
00294                     lpIndexVector.push_back((*it).second);
00295                   }
00296                }
00297             }
00298          }
00299          else if(connection==1){
00300             // ADD TREE
00301             for(size_t i=0; i<gm_[f].numberOfVariables();++i) {
00302                const IndexType u = gm_[f].variableIndex(i);  
00303                for(typename EdgeMapType::const_iterator it=neighbours[u].begin() ; it != neighbours[u].end(); ++it){
00304                   const IndexType v = (*it).first;
00305                   if(variableInSpanningTree[v] == false){
00306                      variableInSpanningTree[v] = true;
00307                      lpIndexVector.push_back((*it).second);
00308                   }
00309                }
00310             }
00311          }
00312          else{
00313             OPENGM_ASSERT(false);
00314          }
00315          higherOrderTerms.back().lpIndices_=lpIndexVector;
00316 
00317          // Check if edges need to be added to have a spanning subgraph
00318          //TODO 
00319       }
00320    }
00321    //std::cout << "Additional Edges: "<<numberOfAdditionalInternalEdges<<std::endl;
00322    return numberOfInternalEdges;
00323 }
00324 
00325 template<class GM, class ACC>
00326 Multicut<GM, ACC>::~Multicut() {
00327    env_.end();
00328 }
00329 
00330 template<class GM, class ACC>
00331 Multicut<GM, ACC>::Multicut
00332 (
00333    const GraphicalModelType& gm,
00334    Parameter para
00335    ) : gm_(gm), parameter_(para) , bound_(-std::numeric_limits<double>::infinity()), infinity_(1e8), integerMode_(false),
00336        EPS_(1e-7)
00337 {
00338    if(typeid(ACC) != typeid(opengm::Minimizer) || typeid(OperatorType) != typeid(opengm::Adder)) {
00339       throw RuntimeError("This implementation does only supports Min-Plus-Semiring.");
00340    } 
00341    if(parameter_.reductionMode_<0 ||parameter_.reductionMode_>3) {
00342       throw RuntimeError("Reduction Mode has to be 1, 2 or 3!");
00343    } 
00344 
00345    //Set Problem Type
00346    setProblemType();
00347    if(problemType_ == INVALID)
00348       throw RuntimeError("Invalid Model for Multicut-Solver! Solver requires a generalized potts model!");
00349 
00350    //Calculate Neighbourhood 
00351    std::vector<double> valuesHigherOrder;
00352    std::vector<HigherOrderTerm> higherOrderTerms;
00353    numberOfInternalEdges_ = getNeighborhood(numberOfTerminalEdges_, neighbours, edgeNodes_ ,higherOrderTerms);
00354    numberOfNodes_         = gm_.numberOfVariables();       
00355      
00356    //Build Objective Value 
00357    constant_=0;
00358    size_t valueSize;
00359    if(numberOfTerminals_==0) valueSize = numberOfInternalEdges_;
00360    else                      valueSize = numberOfTerminalEdges_+numberOfInternalEdges_+numberOfInterTerminalEdges_;
00361    std::vector<double> values (valueSize,0); 
00362  
00363 
00364    for(size_t f=0; f<gm_.numberOfFactors(); ++f) {
00365       if(gm_[f].numberOfVariables() == 1) {
00366          IndexType node = gm_[f].variableIndex(0);
00367          for(LabelType i=0; i<gm_.numberOfLabels(node); ++i) {
00368             for(LabelType j=0; j<gm_.numberOfLabels(node); ++j) {
00369                if(i==j) values[node*numberOfTerminals_+i] += (1.0/(numberOfTerminals_-1)-1) * gm_[f](&j);
00370                else     values[node*numberOfTerminals_+i] += (1.0/(numberOfTerminals_-1))   * gm_[f](&j);
00371             }
00372          }
00373       }
00374       else if(gm_[f].numberOfVariables() == 2) {
00375          if(gm_[f].numberOfLabels(0)==2 && gm_[f].numberOfLabels(1)==2){
00376             IndexType node0 = gm_[f].variableIndex(0);
00377             IndexType node1 = gm_[f].variableIndex(1);
00378             LabelType cc[] = {0,0}; ValueType a = gm_[f](cc);
00379             cc[0]=1;cc[1]=1;        ValueType b = gm_[f](cc);
00380             cc[0]=0;cc[1]=1;        ValueType c = gm_[f](cc);
00381             cc[0]=1;cc[1]=0;        ValueType d = gm_[f](cc);
00382 
00383             values[neighbours[gm_[f].variableIndex(0)][gm_[f].variableIndex(1)]] += ((c+d-a-a) - (b-a))/2.0; 
00384             values[node0*numberOfTerminals_+0] += ((b-a)-(-d+c))/2.0;
00385             values[node1*numberOfTerminals_+0] += ((b-a)-( d-c))/2.0;
00386             constant_ += a;
00387          }else{
00388             LabelType cc0[] = {0,0};
00389             LabelType cc1[] = {0,1};
00390             values[neighbours[gm_[f].variableIndex(0)][gm_[f].variableIndex(1)]] += gm_[f](cc1) - gm_[f](cc0); 
00391             constant_ += gm_[f](cc0);
00392          }
00393       }
00394    }
00395    for(size_t h=0; h<higherOrderTerms.size();++h){
00396       if(higherOrderTerms[h].potts_) {
00397          const IndexType f = higherOrderTerms[h].factorID_; 
00398          higherOrderTerms[h].valueIndex_= valuesHigherOrder.size();
00399          OPENGM_ASSERT(gm_[f].numberOfVariables() > 2);
00400          std::vector<LabelType> cc0(gm_[f].numberOfVariables(),0);
00401          std::vector<LabelType> cc1(gm_[f].numberOfVariables(),0); 
00402          cc1[0] = 1;
00403          valuesHigherOrder.push_back(gm_[f](cc1.begin()) - gm_[f](cc0.begin()) ); 
00404          constant_ += gm_[f](cc0.begin());
00405       }
00406       else{
00407          const IndexType f = higherOrderTerms[h].factorID_;
00408          higherOrderTerms[h].valueIndex_= valuesHigherOrder.size();
00409          if(gm_[f].numberOfVariables() == 3) {
00410             size_t i[] = {0, 1, 2 }; 
00411             valuesHigherOrder.push_back(gm_[f](i)); 
00412             i[0]=0; i[1]=0; i[2]=1;
00413             valuesHigherOrder.push_back(gm_[f](i));
00414             i[0]=0; i[1]=1; i[2]=0;
00415             valuesHigherOrder.push_back(gm_[f](i)); 
00416             i[0]=1; i[1]=0; i[2]=0;
00417             valuesHigherOrder.push_back(gm_[f](i));
00418             i[0]=0; i[1]=0; i[2]=0;
00419             valuesHigherOrder.push_back(gm_[f](i));
00420          }
00421          else if(gm_[f].numberOfVariables() == 4) {
00422             size_t i[] = {0, 1, 2, 3 };//0
00423             if(numberOfTerminals_>=4){
00424                valuesHigherOrder.push_back(gm_[f](i));
00425             }else{
00426                valuesHigherOrder.push_back(0.0);
00427             }
00428             if(numberOfTerminals_>=3){
00429                i[0]=0; i[1]=0; i[2]=1; i[3] = 2;//1
00430                valuesHigherOrder.push_back(gm_[f](i));
00431                i[0]=0; i[1]=1; i[2]=0; i[3] = 2;//2
00432                valuesHigherOrder.push_back(gm_[f](i));
00433                i[0]=0; i[1]=1; i[2]=1; i[3] = 2;//4
00434                valuesHigherOrder.push_back(gm_[f](i));
00435             }else{
00436                valuesHigherOrder.push_back(0.0);
00437                valuesHigherOrder.push_back(0.0);
00438                valuesHigherOrder.push_back(0.0);
00439             }
00440             i[0]=0; i[1]=0; i[2]=0; i[3] = 1;//7
00441             valuesHigherOrder.push_back(gm_[f](i));
00442             i[0]=0; i[1]=1; i[2]=2; i[3] = 0;//8
00443             valuesHigherOrder.push_back(gm_[f](i));
00444             i[0]=0; i[1]=1; i[2]=1; i[3] = 0;//12
00445             valuesHigherOrder.push_back(gm_[f](i));
00446             i[0]=1; i[1]=0; i[2]=2; i[3] = 0;//16
00447             valuesHigherOrder.push_back(gm_[f](i));
00448             i[0]=1; i[1]=0; i[2]=1; i[3] = 0;//18
00449             valuesHigherOrder.push_back(gm_[f](i));
00450             i[0]=0; i[1]=0; i[2]=1; i[3] = 0;//25
00451             valuesHigherOrder.push_back(gm_[f](i));
00452             i[0]=1; i[1]=2; i[2]=0; i[3] = 0;//32
00453             valuesHigherOrder.push_back(gm_[f](i));
00454             i[0]=1; i[1]=1; i[2]=0; i[3] = 0;//33
00455             valuesHigherOrder.push_back(gm_[f](i));
00456             i[0]=0; i[1]=1; i[2]=0; i[3] = 0;//42
00457             valuesHigherOrder.push_back(gm_[f](i));
00458             i[0]=1; i[1]=0; i[2]=0; i[3] = 0;//52
00459             valuesHigherOrder.push_back(gm_[f](i));
00460             i[0]=0; i[1]=0; i[2]=0; i[3] = 0;//63
00461             valuesHigherOrder.push_back(gm_[f](i));
00462          }
00463          else{
00464             throw RuntimeError("Generalized Potts Terms of an order larger than 4 a currently not supported. If U really need them let us know!");
00465          }
00466       }
00467    }
00468 
00469    //count auxilary variables
00470    numberOfHigherOrderValues_ = valuesHigherOrder.size();
00471 
00472    // build LP 
00473    //std::cout << "Higher order auxilary variables " << numberOfHigherOrderValues_ << std::endl;
00474    //std::cout << "TerminalEdges " << numberOfTerminalEdges_ << std::endl;
00475    OPENGM_ASSERT( numberOfTerminalEdges_ == gm_.numberOfVariables()*numberOfTerminals_ );
00476    //std::cout << "InternalEdges " << numberOfInternalEdges_ << std::endl;
00477 
00478    OPENGM_ASSERT(values.size() == numberOfTerminalEdges_+numberOfInternalEdges_+numberOfInterTerminalEdges_);
00479    IloInt N = values.size() + numberOfHigherOrderValues_;
00480    model_ = IloModel(env_);
00481    x_     = IloNumVarArray(env_);
00482    c_     = IloRangeArray(env_);
00483    obj_   = IloMinimize(env_);
00484    sol_   = IloNumArray(env_,N);
00485 
00486    // set variables and objective
00487    x_.add(IloNumVarArray(env_, N, 0, 1, ILOFLOAT));
00488 
00489    IloNumArray    obj(env_,N);
00490    for (size_t i=0; i< values.size();++i) {
00491       if(values[i]==0)
00492          obj[i] = 0;//1e-50; //for numerical reasons
00493       else
00494          obj[i] = values[i];
00495    }
00496    {
00497       size_t count =0;
00498       for (size_t i=0; i<valuesHigherOrder.size();++i) {
00499          obj[values.size()+count++] = valuesHigherOrder[i];
00500       }
00501       OPENGM_ASSERT(count == numberOfHigherOrderValues_);
00502    }
00503    obj_.setLinearCoefs(x_,obj);
00504  
00505    // set constraints 
00506    size_t constraintCounter = 0;
00507    // multiway cut constraints
00508    if(problemType_ == MWC) {
00509       // From each internal-node only one terminal-edge should be 0
00510       for(IndexType var=0; var<gm_.numberOfVariables(); ++var) {
00511          c_.add(IloRange(env_, numberOfTerminals_-1, numberOfTerminals_-1));
00512          for(LabelType i=0; i<gm_.numberOfLabels(var); ++i) {
00513             c_[constraintCounter].setLinearCoef(x_[var*numberOfTerminals_+i],1);
00514          }
00515          ++constraintCounter;
00516       }
00517       // Inter-terminal-edges have to be 1
00518       for(size_t i=0; i<(size_t)(numberOfTerminals_*(numberOfTerminals_-1)/2); ++i) {
00519          c_.add(IloRange(env_, 1, 1));
00520          c_[constraintCounter].setLinearCoef(x_[numberOfTerminalEdges_+numberOfInternalEdges_+i],1);
00521          ++constraintCounter;
00522       }
00523    }
00524 
00525    
00526    // higher order constraints
00527    size_t count = 0;
00528    for(size_t i=0; i<higherOrderTerms.size(); ++i) {
00529       size_t factorID = higherOrderTerms[i].factorID_;
00530       size_t numVar   = gm_[factorID].numberOfVariables();
00531       OPENGM_ASSERT(numVar>2);
00532 
00533       if(higherOrderTerms[i].potts_) {
00534          double b = higherOrderTerms[i].lpIndices_.size();
00535          
00536 
00537          // Add only one constraint is sufficient with {0,1} constraints
00538          // ------------------------------------------------------------
00539          // ** -|E|+1 <= -|E|*y_H+\sum_{e\in H} y_e <= 0 
00540          if(parameter_.reductionMode_ % 2 == 1){
00541             c_.add(IloRange(env_, -b+1 , 0));
00542             for(size_t i1=0; i1<higherOrderTerms[i].lpIndices_.size();++i1) {
00543                const LPIndexType edgeID = higherOrderTerms[i].lpIndices_[i1]; 
00544                c_[constraintCounter].setLinearCoef(x_[edgeID],1);
00545             }
00546             c_[constraintCounter].setLinearCoef(x_[values.size()+count],-b);
00547             constraintCounter += 1;
00548          }
00549          // In general this additional contraints and more local constraints leeds to tighter relaxations
00550          // ---------------------------------------------------------------------------------------------
00551          if(parameter_.reductionMode_ % 4 >=2){ 
00552             // ** y_H <= sum_{e \in H} y_e
00553             c_.add(IloRange(env_, -2.0*b, 0));
00554             for(size_t i1=0; i1<higherOrderTerms[i].lpIndices_.size();++i1) {
00555                const LPIndexType edgeID = higherOrderTerms[i].lpIndices_[i1]; 
00556                c_[constraintCounter].setLinearCoef(x_[edgeID],-1);
00557             }
00558             c_[constraintCounter].setLinearCoef(x_[values.size()+count],1);
00559             constraintCounter += 1;
00560          
00561             // ** forall e \in H : y_H>=y_e
00562             for(size_t i1=0; i1<higherOrderTerms[i].lpIndices_.size();++i1) {
00563                const LPIndexType edgeID = higherOrderTerms[i].lpIndices_[i1]; 
00564                c_.add(IloRange(env_, 0 , 1));
00565                c_[constraintCounter].setLinearCoef(x_[edgeID],-1);
00566                c_[constraintCounter].setLinearCoef(x_[values.size()+count],1); 
00567                constraintCounter += 1;
00568             }        
00569          }
00570          count++;
00571       }else{
00572          if(numVar==3) {
00573             OPENGM_ASSERT(higherOrderTerms[i].valueIndex_<=valuesHigherOrder.size());
00574             LPIndexType edgeIDs[3];
00575             edgeIDs[0] = neighbours[gm_[factorID].variableIndex(0)][gm_[factorID].variableIndex(1)];
00576             edgeIDs[1] = neighbours[gm_[factorID].variableIndex(0)][gm_[factorID].variableIndex(2)];
00577             edgeIDs[2] = neighbours[gm_[factorID].variableIndex(1)][gm_[factorID].variableIndex(2)];
00578                
00579             const unsigned int P[] = {0,1,2,4,7,8,12,16,18,25,32,33,42,52,63};
00580             double c[3];  
00581 
00582             c_.add(IloRange(env_, 1, 1));
00583             size_t lvc=0;
00584             for(size_t p=0; p<5; p++){
00585                if(true || valuesHigherOrder[higherOrderTerms[i].valueIndex_+p]!=0){   
00586                   c_[constraintCounter].setLinearCoef(x_[values.size()+count+lvc],1);
00587                   ++lvc;
00588                }
00589             }
00590             ++constraintCounter;  
00591 
00592             for(size_t p=0; p<5; p++){
00593                if(true || valuesHigherOrder[higherOrderTerms[i].valueIndex_+p]!=0){
00594                   double ub = 2.0;
00595                   double lb = 0.0;
00596                   unsigned int mask = 1;
00597                   for(size_t n=0; n<3; n++){
00598                      if(P[p] & mask){
00599                         c[n] = -1.0;
00600                         ub--;
00601                         lb--; 
00602                      }
00603                      else{
00604                         c[n] = 1.0; 
00605                      }
00606                      mask = mask << 1;
00607                   }
00608                   c_.add(IloRange(env_, lb, ub));
00609                   for(size_t n=0; n<3; n++){
00610                      c_[constraintCounter].setLinearCoef(x_[edgeIDs[n]],c[n]);
00611                   }
00612                   c_[constraintCounter].setLinearCoef(x_[values.size()+count],-1);
00613                   ++constraintCounter;  
00614                
00615                   for(size_t n=0; n<3; n++){
00616                      if(c[n]>0){
00617                         c_.add(IloRange(env_, 0, 1));
00618                         c_[constraintCounter].setLinearCoef(x_[edgeIDs[n]],1);
00619                         c_[constraintCounter].setLinearCoef(x_[values.size()+count],-1);
00620                         ++constraintCounter;     
00621                      }else{
00622                         c_.add(IloRange(env_, -1, 0));
00623                         c_[constraintCounter].setLinearCoef(x_[edgeIDs[n]],-1);
00624                         c_[constraintCounter].setLinearCoef(x_[values.size()+count],-1);
00625                         ++constraintCounter;     
00626                      }     
00627                   }
00628                   ++count;
00629                }
00630             }
00631          }
00632          else if(numVar==4) {                  
00633             OPENGM_ASSERT(higherOrderTerms[i].valueIndex_<=valuesHigherOrder.size());
00634             LPIndexType edgeIDs[6];
00635             edgeIDs[0] = neighbours[gm_[factorID].variableIndex(0)][gm_[factorID].variableIndex(1)];
00636             edgeIDs[1] = neighbours[gm_[factorID].variableIndex(0)][gm_[factorID].variableIndex(2)];
00637             edgeIDs[2] = neighbours[gm_[factorID].variableIndex(1)][gm_[factorID].variableIndex(2)];
00638             edgeIDs[3] = neighbours[gm_[factorID].variableIndex(0)][gm_[factorID].variableIndex(3)];
00639             edgeIDs[4] = neighbours[gm_[factorID].variableIndex(1)][gm_[factorID].variableIndex(3)];
00640             edgeIDs[5] = neighbours[gm_[factorID].variableIndex(2)][gm_[factorID].variableIndex(3)];
00641           
00642                
00643             const unsigned int P[] = {0,1,2,4,7,8,12,16,18,25,32,33,42,52,63};
00644             double c[6];
00645 
00646             c_.add(IloRange(env_, 1, 1));
00647             size_t lvc=0;
00648             for(size_t p=0; p<15; p++){
00649                if(true ||valuesHigherOrder[higherOrderTerms[i].valueIndex_+p]!=0){   
00650                   c_[constraintCounter].setLinearCoef(x_[values.size()+count+lvc],1);
00651                   ++lvc;
00652                }
00653             }
00654             ++constraintCounter;  
00655 
00656 
00657             for(size_t p=0; p<15; p++){
00658                double ub = 5.0;
00659                double lb = 0.0;
00660                unsigned int mask = 1;
00661                for(size_t n=0; n<6; n++){
00662                   if(P[p] & mask){
00663                      c[n] = -1.0;
00664                      ub--;
00665                      lb--; 
00666                   }
00667                   else{
00668                      c[n] = 1.0; 
00669                   }
00670                   mask = mask << 1;
00671                }
00672                c_.add(IloRange(env_, lb, ub));
00673                for(size_t n=0; n<6; n++){
00674                   c_[constraintCounter].setLinearCoef(x_[edgeIDs[n]],c[n]);
00675                }
00676                c_[constraintCounter].setLinearCoef(x_[values.size()+count],-1);
00677                ++constraintCounter;  
00678                
00679                for(size_t n=0; n<6; n++){
00680                   if(c[n]>0){
00681                      c_.add(IloRange(env_, 0, 1));
00682                      c_[constraintCounter].setLinearCoef(x_[edgeIDs[n]],1);
00683                      c_[constraintCounter].setLinearCoef(x_[values.size()+count],-1);
00684                      ++constraintCounter;     
00685                   }else{
00686                      c_.add(IloRange(env_, -1, 0));
00687                      c_[constraintCounter].setLinearCoef(x_[edgeIDs[n]],-1);
00688                      c_[constraintCounter].setLinearCoef(x_[values.size()+count],-1);
00689                      ++constraintCounter;     
00690                   }     
00691                }
00692                ++count;
00693             }  
00694          }
00695          else{
00696             OPENGM_ASSERT(false);
00697          }
00698       }
00699    } 
00700 
00701 
00702    model_.add(obj_);
00703    if(constraintCounter>0) {
00704       model_.add(c_);
00705    }
00706 
00707    // initialize solver
00708    cplex_ = IloCplex(model_);
00709 
00710 }
00711 
00712 template<class GM, class ACC>
00713 typename Multicut<GM, ACC>::ProblemType Multicut<GM, ACC>::setProblemType() {
00714    problemType_ = MC;
00715    for(size_t f=0; f<gm_.numberOfFactors();++f) {
00716       if(gm_[f].numberOfVariables()==1) {
00717          problemType_ = MWC;
00718       }
00719       if(gm_[f].numberOfVariables()>1) {
00720          for(size_t i=0; i<gm_[f].numberOfVariables();++i) {
00721             if(gm_[f].numberOfLabels(i)<gm_.numberOfVariables()) {
00722                problemType_ = MWC;
00723             }
00724          }
00725       }
00726       if(gm_[f].numberOfVariables()==2 && gm_[f].numberOfLabels(0)==2 && gm_[f].numberOfLabels(1)==2){
00727          problemType_ = MWC; //OK - can be reparmetrized
00728       }
00729       else if(gm_[f].numberOfVariables()>1 && !gm_[f].isGeneralizedPotts()) {
00730          problemType_ = INVALID;
00731          break;
00732       }
00733    } 
00734  
00735    // set member variables
00736    if(problemType_ == MWC) {
00737       numberOfTerminals_ = gm_.numberOfLabels(0); 
00738       numberOfInterTerminalEdges_ = (numberOfTerminals_*(numberOfTerminals_-1))/2; 
00739       numberOfTerminalEdges_ = 0;
00740       for(IndexType i=0; i<gm_.numberOfVariables(); ++i) {
00741          for(LabelType j=0; j<gm_.numberOfLabels(i); ++j) {
00742             ++numberOfTerminalEdges_;
00743          }
00744       } 
00745    }
00746    else{
00747       numberOfTerminalEdges_ = 0;
00748       numberOfTerminals_     = 0;
00749       numberOfInterTerminalEdges_ = 0;
00750    } 
00751    return problemType_;
00752 }
00753 
00754 //**********************************************
00755 //**
00756 //** Functions that find violated Constraints
00757 //**
00758 //**********************************************
00759 
00760 template<class GM, class ACC>
00761 size_t Multicut<GM, ACC>::removeUnusedConstraints()
00762 { 
00763    std::cout << "Not Implemented " <<std::endl ; 
00764    return 0;
00765 }
00766 
00767 
00768 
00769 template<class GM, class ACC>
00770 size_t Multicut<GM, ACC>::enforceIntegerConstraints()
00771 {
00772    size_t N=numberOfTerminalEdges_;
00773    if (N==0) N = numberOfInternalEdges_;
00774 
00775    for(size_t i=0; i<N; ++i)
00776       model_.add(IloConversion(env_, x_[i], ILOBOOL));
00777    for(size_t i=0; i<numberOfHigherOrderValues_; ++i)
00778       model_.add(IloConversion(env_, x_[numberOfTerminalEdges_+numberOfInternalEdges_+numberOfInterTerminalEdges_+i], ILOBOOL));
00779    integerMode_ = true;
00780 
00781    return N+numberOfHigherOrderValues_;
00782 }
00783 
00790 template<class GM, class ACC>
00791 size_t Multicut<GM, ACC>::findTerminalTriangleConstraints(IloRangeArray& constraint)
00792 {
00793    OPENGM_ASSERT(problemType_ == MWC);
00794    if(!(problemType_ == MWC)) return 0;
00795    size_t tempConstrainCounter = constraintCounter_;
00796 
00797    size_t u,v;
00798    for(size_t i=0; i<numberOfInternalEdges_;++i) {
00799       u = edgeNodes_[i].first;//[0];
00800       v = edgeNodes_[i].second;//[1];
00801       for(size_t l=0; l<numberOfTerminals_;++l) {
00802          if(-sol_[numberOfTerminalEdges_+i]+sol_[u*numberOfTerminals_+l]+sol_[v*numberOfTerminals_+l]<-EPS_) {
00803             constraint.add(IloRange(env_, 0 , 2));
00804             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],-1);
00805             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+l],1);
00806             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+l],1);
00807             ++constraintCounter_;
00808          }
00809          if(sol_[numberOfTerminalEdges_+i]-sol_[u*numberOfTerminals_+l]+sol_[v*numberOfTerminals_+l]<-EPS_) {
00810             constraint.add(IloRange(env_, 0 , 2));
00811             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00812             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+l],-1);
00813             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+l],1);
00814             ++constraintCounter_;
00815          }
00816          if(sol_[numberOfTerminalEdges_+i]+sol_[u*numberOfTerminals_+l]-sol_[v*numberOfTerminals_+l]<-EPS_) {
00817             constraint.add(IloRange(env_, 0 , 2));
00818             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00819             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+l],1);
00820             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+l],-1);
00821             ++constraintCounter_;
00822          }
00823       }
00824       if(constraintCounter_-tempConstrainCounter >= parameter_.maximalNumberOfConstraintsPerRound_)
00825          break;
00826    }
00827    return constraintCounter_-tempConstrainCounter;
00828 }
00829 
00836 template<class GM, class ACC>
00837 size_t Multicut<GM, ACC>::findMultiTerminalConstraints(IloRangeArray& constraint)
00838 {
00839    OPENGM_ASSERT(problemType_ == MWC);
00840    if(!(problemType_ == MWC)) return 0;
00841    size_t tempConstrainCounter = constraintCounter_;
00842 
00843    size_t u,v;
00844    for(size_t i=0; i<numberOfInternalEdges_;++i) {
00845       u = edgeNodes_[i].first;//[0];
00846       v = edgeNodes_[i].second;//[1];
00847       std::vector<size_t> terminals1;
00848       std::vector<size_t> terminals2;
00849       double sum1 = 0;
00850       double sum2 = 0;
00851       for(size_t l=0; l<numberOfTerminals_;++l) {
00852          if(sol_[u*numberOfTerminals_+l]-sol_[v*numberOfTerminals_+l] > EPS_) {
00853             terminals1.push_back(l);
00854             sum1 += sol_[u*numberOfTerminals_+l]-sol_[v*numberOfTerminals_+l];
00855          }
00856          if(sol_[v*numberOfTerminals_+l]-sol_[u*numberOfTerminals_+l] > EPS_) {
00857             terminals2.push_back(l);
00858             sum2 +=sol_[v*numberOfTerminals_+l]-sol_[u*numberOfTerminals_+l];
00859          }
00860       }
00861       if(sol_[numberOfTerminalEdges_+i]-sum1<-EPS_) {
00862          constraint.add(IloRange(env_, 0 , 200000));
00863          constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00864          for(size_t k=0; k<terminals1.size(); ++k) {
00865             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+terminals1[k]],-1);
00866             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+terminals1[k]],1);
00867          }
00868          ++constraintCounter_;
00869       }
00870       if(sol_[numberOfTerminalEdges_+i]-sum2<-EPS_) {
00871          constraint.add(IloRange(env_, 0 , 200000));
00872          constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00873          for(size_t k=0; k<terminals2.size(); ++k) {
00874             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+terminals2[k]],1);
00875             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+terminals2[k]],-1);
00876          }
00877          ++constraintCounter_;
00878       } 
00879       if(constraintCounter_-tempConstrainCounter >= parameter_.maximalNumberOfConstraintsPerRound_)
00880          break;
00881    } 
00882    return constraintCounter_-tempConstrainCounter;
00883 }
00884 
00891 template<class GM, class ACC>
00892 size_t Multicut<GM, ACC>::findIntegerTerminalTriangleConstraints(IloRangeArray& constraint, std::vector<LabelType>& conf)
00893 { 
00894    OPENGM_ASSERT(integerMode_);
00895    OPENGM_ASSERT(problemType_ == MWC);
00896    if(!(problemType_ == MWC)) return 0;
00897    size_t tempConstrainCounter = constraintCounter_;
00898 
00899    size_t u,v;
00900    for(size_t i=0; i<numberOfInternalEdges_;++i) {
00901       u = edgeNodes_[i].first;//[0];
00902       v = edgeNodes_[i].second;//[1];
00903       if(sol_[numberOfTerminalEdges_+i]<EPS_ && (conf[u]!=conf[v]) ) {
00904          if(sol_[numberOfTerminalEdges_+i]-sol_[u*numberOfTerminals_+conf[u]]+sol_[v*numberOfTerminals_+conf[u]]<=0) {
00905             constraint.add(IloRange(env_, 0 , 10));
00906             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00907             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+conf[u]],-1);
00908             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+conf[u]],1);
00909             ++constraintCounter_;
00910          }
00911          if(sol_[numberOfTerminalEdges_+i]-sol_[u*numberOfTerminals_+conf[u]]+sol_[v*numberOfTerminals_+conf[u]]<=0) {
00912             constraint.add(IloRange(env_, 0 , 10));
00913             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00914             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+conf[u]],1);
00915             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+conf[u]],-1);
00916             ++constraintCounter_;
00917          }
00918          if(sol_[numberOfTerminalEdges_+i]-sol_[u*numberOfTerminals_+conf[v]]+sol_[v*numberOfTerminals_+conf[v]]<=0) {
00919             constraint.add(IloRange(env_, 0 , 10));
00920             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00921             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+conf[v]],-1);
00922             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+conf[v]],1);
00923             ++constraintCounter_;
00924          }
00925          if(sol_[numberOfTerminalEdges_+i]+sol_[u*numberOfTerminals_+conf[v]]-sol_[v*numberOfTerminals_+conf[v]]<=0) {
00926             constraint.add(IloRange(env_, 0 , 10));
00927             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],1);
00928             constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+conf[v]],1);
00929             constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+conf[v]],-1);
00930             ++constraintCounter_;
00931          }
00932       }
00933       if(sol_[numberOfTerminalEdges_+i]>1-EPS_ && (conf[u]==conf[v]) ) {
00934          constraint.add(IloRange(env_, 0 , 10));
00935          constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],-1);
00936          constraint[constraintCounter_].setLinearCoef(x_[u*numberOfTerminals_+conf[u]],1);
00937          constraint[constraintCounter_].setLinearCoef(x_[v*numberOfTerminals_+conf[v]],1);
00938          ++constraintCounter_;
00939       }
00940       if(constraintCounter_-tempConstrainCounter >= parameter_.maximalNumberOfConstraintsPerRound_)
00941          break;
00942    }
00943    return constraintCounter_-tempConstrainCounter;
00944 }
00945 
00950 template<class GM, class ACC>
00951 size_t Multicut<GM, ACC>::findCycleConstraints(
00952    IloRangeArray& constraint,
00953    bool addOnlyFacetDefiningConstraints = true,
00954    bool usePreBounding = true
00955 )
00956 { 
00957    std::vector<LabelType> partit;
00958    std::vector<std::list<size_t> > neighbours0;
00959 
00960    size_t tempConstrainCounter = constraintCounter_;
00961  
00962    if(usePreBounding){
00963       partition(partit,neighbours0,1-EPS_);
00964    }
00965   
00966    std::map<std::pair<IndexType,IndexType>,size_t> counter;
00967    for(size_t i=0; i<numberOfInternalEdges_;++i) {
00968       
00969       IndexType u = edgeNodes_[i].first;//[0];
00970       IndexType v = edgeNodes_[i].second;//[1]; 
00971       
00972       if(usePreBounding && partit[u] != partit[v])
00973          continue;
00974 
00975       OPENGM_ASSERT(i+numberOfTerminalEdges_ == neighbours[u][v]);
00976       OPENGM_ASSERT(i+numberOfTerminalEdges_ == neighbours[v][u]);
00977       
00978       if(sol_[numberOfTerminalEdges_+i]>EPS_){
00979          //search for cycle
00980          std::vector<IndexType> path;
00981          const double pathLength = shortestPath(u,v,neighbours,sol_,path,sol_[numberOfTerminalEdges_+i],addOnlyFacetDefiningConstraints);
00982          if(sol_[numberOfTerminalEdges_+i]-EPS_>pathLength){
00983             OPENGM_ASSERT(path.size()>2);
00984             constraint.add(IloRange(env_, 0 , 1000000000));
00985             constraint[constraintCounter_].setLinearCoef(x_[numberOfTerminalEdges_+i],-1);
00986             for(size_t n=0;n<path.size()-1;++n){
00987                constraint[constraintCounter_].setLinearCoef(x_[neighbours[path[n]][path[n+1]]],1);
00988             }
00989             ++constraintCounter_; 
00990          }
00991       } 
00992       if(constraintCounter_-tempConstrainCounter >= parameter_.maximalNumberOfConstraintsPerRound_)
00993          break;
00994    }
00995    return constraintCounter_-tempConstrainCounter;
00996 }
00997 
00998 template<class GM, class ACC>
00999 size_t Multicut<GM, ACC>::findOddWheelConstraints(IloRangeArray& constraints){
01000    size_t tempConstrainCounter = constraintCounter_;
01001    std::vector<IndexType> var2node(gm_.numberOfVariables(),std::numeric_limits<IndexType>::max());
01002    for(size_t center=0; center<gm_.numberOfVariables();++center){
01003       var2node.assign(gm_.numberOfVariables(),std::numeric_limits<IndexType>::max());
01004       size_t N = neighbours[center].size();
01005       std::vector<IndexType> node2var(N);
01006       std::vector<EdgeMapType> E(2*N);
01007       std::vector<double>     w;
01008       typename EdgeMapType::const_iterator it;
01009       size_t id=0;
01010       for(it=neighbours[center].begin() ; it != neighbours[center].end(); ++it) {
01011          IndexType var = (*it).first;
01012          node2var[id]  = var;
01013          var2node[var] = id++;
01014       } 
01015      
01016       for(it=neighbours[center].begin() ; it != neighbours[center].end(); ++it) { 
01017          const IndexType var1 = (*it).first;
01018          const LPIndexType u = var2node[var1];   
01019          typename EdgeMapType::const_iterator it2;
01020          for(it2=neighbours[var1].begin() ; it2 != neighbours[var1].end(); ++it2) {
01021             const IndexType var2 = (*it2).first; 
01022             const LPIndexType v = var2node[var2];   
01023             if( v !=  std::numeric_limits<IndexType>::max()){
01024                if(u<v){
01025                   E[2*u][2*v+1]=w.size();
01026                   E[2*v+1][2*u]=w.size(); 
01027                   E[2*u+1][2*v]=w.size();
01028                   E[2*v][2*u+1]=w.size();
01029                   double weight = 0.5-sol_[neighbours[var1][var2]]+0.5*(sol_[neighbours[center][var1]]+sol_[neighbours[center][var2]]); 
01030                   //OPENGM_ASSERT(weight>-1e-7);
01031                   if(weight<0) weight=0;
01032                   w.push_back(weight);
01033                  
01034                }
01035             }
01036          }
01037       }
01038      
01039       //Search for odd wheels
01040       for(size_t n=0; n<N;++n) {
01041          std::vector<IndexType> path;
01042          const double pathLength = shortestPath(2*n,2*n+1,E,w,path,1e22,false);
01043          if(pathLength<0.5-EPS_){// && (path.size())>3){
01044             OPENGM_ASSERT((path.size())>3);
01045             OPENGM_ASSERT(((path.size())/2)*2 == path.size() );
01046 
01047             constraints.add(IloRange(env_, -100000 , (path.size()-2)/2 ));
01048             for(size_t k=0;k<path.size()-1;++k){
01049                constraints[constraintCounter_].setLinearCoef(x_[neighbours[center][node2var[path[k]/2]]],-1);
01050             }
01051             for(size_t k=0;k<path.size()-1;++k){
01052                const IndexType u= node2var[path[k]/2];
01053                const IndexType v= node2var[path[k+1]/2];
01054                constraints[constraintCounter_].setLinearCoef(x_[neighbours[u][v]],1);
01055             }
01056             ++constraintCounter_; 
01057          } 
01058          if(constraintCounter_-tempConstrainCounter >= parameter_.maximalNumberOfConstraintsPerRound_)
01059             break;
01060       }
01061  
01062       //Reset var2node
01063       for(it=neighbours[center].begin() ; it != neighbours[center].end(); ++it) {
01064          var2node[(*it).first] = std::numeric_limits<IndexType>::max();
01065       }
01066     
01067    }
01068    
01069    return constraintCounter_-tempConstrainCounter;
01070 }  
01071   
01077 template<class GM, class ACC>
01078 size_t Multicut<GM, ACC>::findIntegerCycleConstraints(
01079    IloRangeArray& constraint,
01080    bool addFacetDefiningConstraintsOnly=true
01081 )
01082 {
01083    OPENGM_ASSERT(integerMode_);
01084    std::vector<LabelType> partit(numberOfNodes_,EPS_);
01085    std::vector<std::list<size_t> > neighbours0;
01086    partition(partit,neighbours0);
01087    size_t tempConstrainCounter = constraintCounter_;
01088   
01089    //Find Violated Cycles inside a Partition
01090    size_t u,v;
01091    for(size_t i=0; i<numberOfInternalEdges_;++i) {
01092       u = edgeNodes_[i].first;//[0];
01093       v = edgeNodes_[i].second;//[1];
01094       OPENGM_ASSERT(partit[u] >= 0);
01095       if(sol_[numberOfTerminalEdges_+i]>=1-EPS_ && partit[u] == partit[v]) {
01096          //find shortest path from u to v by BFS
01097          std::queue<size_t> nodeList;
01098          std::vector<size_t> path(numberOfNodes_,std::numeric_limits<size_t>::max());
01099          size_t n = u;
01100          while(n!=v) {
01101             std::list<size_t>::iterator it;
01102             for(it=neighbours0[n].begin() ; it != neighbours0[n].end(); ++it) {
01103                if(path[*it]==std::numeric_limits<size_t>::max()) {
01104                   //Check if this path is chordless 
01105                   if(addFacetDefiningConstraintsOnly) {
01106                      bool isCordless = true;
01107                      size_t s = n;
01108                      const size_t c = *it;
01109                      while(s!=u){
01110                         s = path[s];
01111                         if(s==u && c==v) continue;
01112                         if(neighbours[c].find(s)!=neighbours[c].end()) {
01113                            isCordless = false;
01114                            break;
01115                         } 
01116                      }
01117                      if(isCordless){
01118                         path[*it]=n;
01119                         nodeList.push(*it);
01120                      }
01121                   }
01122                   else{
01123                      path[*it]=n;
01124                      nodeList.push(*it);
01125                   }
01126                }
01127             }
01128             if(nodeList.size()==0)
01129                break;
01130             n = nodeList.front(); nodeList.pop();
01131          }
01132          if(path[v] != std::numeric_limits<size_t>::max()){
01133             if(!integerMode_){//check if it is realy violated
01134                double w=0;
01135                while(n!=u) {
01136                   w += sol_[neighbours[n][path[n]]];
01137                   n=path[n];
01138                }
01139                if(sol_[neighbours[u][v]]-EPS_<w)//constraint is not violated
01140                   continue;
01141             }
01142 
01143             constraint.add(IloRange(env_, 0 , 1000000000));
01144             constraint[constraintCounter_].setLinearCoef(x_[neighbours[u][v]],-1);
01145             while(n!=u) {
01146                constraint[constraintCounter_].setLinearCoef(x_[neighbours[n][path[n]]],1);
01147                n=path[n];
01148             }
01149             ++constraintCounter_;
01150          } 
01151          if(constraintCounter_-tempConstrainCounter >= parameter_.maximalNumberOfConstraintsPerRound_)
01152             break;
01153       }
01154       if(constraintCounter_-tempConstrainCounter >= parameter_.maximalNumberOfConstraintsPerRound_)
01155          break;
01156    }
01157    return constraintCounter_-tempConstrainCounter;
01158 }
01159 //************************************************
01160 
01161 template <class GM, class ACC>
01162 InferenceTermination
01163 Multicut<GM,ACC>::infer()
01164 {
01165    EmptyVisitorType mcv;
01166    return infer(mcv);
01167 }
01168 
01169 template <class GM, class ACC>
01170 void
01171 Multicut<GM,ACC>::initCplex()
01172 {
01173 
01174    cplex_.setParam(IloCplex::Threads, parameter_.numThreads_);
01175    cplex_.setParam(IloCplex::CutUp, parameter_.cutUp_);
01176    cplex_.setParam(IloCplex::MIPDisplay,0);
01177    cplex_.setParam(IloCplex::BarDisplay,0);
01178    cplex_.setParam(IloCplex::NetDisplay,0);
01179    cplex_.setParam(IloCplex::SiftDisplay,0);
01180    cplex_.setParam(IloCplex::SimDisplay,0);
01181 
01182    cplex_.setParam(IloCplex::EpOpt,1e-9);
01183    cplex_.setParam(IloCplex::EpRHS,1e-9);
01184    cplex_.setParam(IloCplex::EpInt,0);
01185    cplex_.setParam(IloCplex::EpAGap,0);
01186    cplex_.setParam(IloCplex::EpGap,0);
01187 
01188    if(parameter_.verbose_ == true && parameter_.verboseCPLEX_) {
01189       cplex_.setParam(IloCplex::MIPDisplay,2);
01190       cplex_.setParam(IloCplex::BarDisplay,1);
01191       cplex_.setParam(IloCplex::NetDisplay,1);
01192       cplex_.setParam(IloCplex::SiftDisplay,1);
01193       cplex_.setParam(IloCplex::SimDisplay,1);
01194    }
01195 }
01196 
01197 
01198 template <class GM, class ACC>
01199 template<class VisitorType>
01200 InferenceTermination
01201 Multicut<GM,ACC>::infer(VisitorType& mcv)
01202 {
01203 
01204 
01205 
01206    std::vector<LabelType> conf(gm_.numberOfVariables());
01207    initCplex();
01208    //cplex_.setParam(IloCplex::RootAlg, IloCplex::Primal);
01209     
01210    if(problemType_ == INVALID){ 
01211       throw RuntimeError("Error:  Model can not be solved!"); 
01212    }
01213    else if(!readWorkFlow(parameter_.workFlow_)){//Use given workflow if posible
01214       std::cout << "Error: can not parse workflow : " << parameter_.workFlow_ <<std::endl;
01215       std::cout << "Using default workflow ";
01216       if(problemType_ == MWC){
01217          std::cout << "(TTC)(MTC)(IC)(CC-IFD,TTC-I)" <<std::endl;
01218          readWorkFlow("(TTC)(MTC)(IC)(CC-IFD,TTC-I)");
01219       }
01220       else if(problemType_ == MC){
01221          std::cout << "(CC-FDB)(IC)(CC-I)" <<std::endl;
01222          readWorkFlow("(CC-FDB)(IC)(CC-I)");
01223       }
01224       else{
01225          throw RuntimeError("Error:  Model can not be solved!"); 
01226       }
01227    }
01228 
01229 
01230    Timer timer,timer2;
01231    timer.tic();     
01232    mcv.begin(*this);    
01233    size_t workingState = 0;
01234    while(workingState<workFlow_.size()){
01235       protocolateTiming_.push_back(std::vector<double>(20,0));
01236       protocolateConstraints_.push_back(std::vector<size_t>(20,0));
01237       std::vector<double>& T = protocolateTiming_.back();
01238       std::vector<size_t>& C = protocolateConstraints_.back();
01239 
01240       // Check for timeout
01241       timer.toc();
01242       if(timer.elapsedTime()>parameter_.timeOut_) {
01243          break;
01244       }
01245       //check for integer constraints   
01246       for (size_t it=1; it<10000000000; ++it) {
01247          cplex_.setParam(IloCplex::Threads, parameter_.numThreads_); 
01248          timer2.tic();
01249          if(!cplex_.solve()) {
01250             std::cout << "failed to optimize. " <<cplex_.getStatus()<< std::endl;
01251             mcv(*this);  
01252             return UNKNOWN;
01253          }
01254          if(!integerMode_)
01255             //bound_ = calcBound();
01256             bound_ = cplex_.getObjValue()+constant_;
01257          else{
01258             bound_ = cplex_.getBestObjValue()+constant_;
01259             if(!cplex_.solveFixed()) {
01260                std::cout << "failed to fixed optimize." << std::endl; 
01261                mcv(*this);
01262                return UNKNOWN;
01263             }
01264          } 
01265          cplex_.getValues(sol_, x_);
01266          timer2.toc();
01267          T[Protocol_ID_Solve] += timer2.elapsedTime();
01268          mcv(*this);
01269          
01270          //std::cout << "... done."<<std::endl;
01271          
01272          //Find Violated Constraints
01273          IloRangeArray constraint = IloRangeArray(env_);
01274          constraintCounter_ = 0;
01275          
01276          //std::cout << "Search violated constraints ..." <<std::endl; 
01277        
01278 
01279          size_t cycleConstraints = std::numeric_limits<size_t>::max();
01280          bool   constraintAdded = false;
01281          for(std::vector<size_t>::iterator it=workFlow_[workingState].begin() ; it != workFlow_[workingState].end(); it++ ){
01282             size_t n = 0;
01283             size_t protocol_ID = Protocol_ID_Unknown;
01284             timer2.tic();
01285             if(*it == Action_ID_TTC){
01286                if(parameter_.verbose_) std::cout << "* Add  terminal triangle constraints: " << std::flush;
01287                n = findTerminalTriangleConstraints(constraint);
01288                if(parameter_.verbose_) std::cout << n << std::endl;
01289                protocol_ID = Protocol_ID_TTC;
01290             } 
01291             else if(*it == Action_ID_TTC_I){ 
01292                if(!integerMode_){
01293                   throw RuntimeError("Error: Calling integer terminal triangle constraint (TTC-I) seperation provedure before switching in integer mode (IC)"); 
01294                }
01295                if(parameter_.verbose_) std::cout << "* Add integer terminal triangle constraints: " << std::flush;
01296                arg(conf);
01297                n = findIntegerTerminalTriangleConstraints(constraint, conf);
01298                if(parameter_.verbose_) std::cout << n  << std::endl;
01299                protocol_ID = Protocol_ID_TTC;
01300         
01301             }
01302             else if(*it == Action_ID_MTC){
01303                if(parameter_.verbose_) std::cout << "* Add multi terminal constraints: " << std::flush;
01304                n = findMultiTerminalConstraints(constraint);
01305                if(parameter_.verbose_) std::cout <<  n << std::endl;
01306                protocol_ID = Protocol_ID_MTC;
01307         
01308             }
01309             else if(*it == Action_ID_CC_I){
01310                if(!integerMode_){
01311                   throw RuntimeError("Error: Calling integer cycle constraints (CC-I) seperation provedure before switching in integer mode (IC)"); 
01312                }
01313                if(parameter_.verbose_) std::cout << "Add integer cycle constraints: " << std::flush;
01314                n = findIntegerCycleConstraints(constraint, false);
01315                if(parameter_.verbose_) std::cout << n  << std::endl; 
01316                protocol_ID = Protocol_ID_CC;
01317             } 
01318             else if(*it == Action_ID_CC_IFD){ 
01319                if(!integerMode_){
01320                   throw RuntimeError("Error: Calling facet defining integer cycle constraints (CC-IFD) seperation provedure before switching in integer mode (IC)"); 
01321                }
01322                if(parameter_.verbose_) std::cout << "Add facet defining integer cycle constraints: " << std::flush;
01323                n = findIntegerCycleConstraints(constraint, true);
01324                if(parameter_.verbose_) std::cout << n  << std::endl; 
01325                protocol_ID = Protocol_ID_CC;
01326             }
01327             else if(*it == Action_ID_CC){
01328                if(parameter_.verbose_) std::cout << "Add cycle constraints: " << std::flush;     
01329                n = findCycleConstraints(constraint, false, false);
01330                cycleConstraints=n;
01331                if(parameter_.verbose_) std::cout  << n << std::endl; 
01332                protocol_ID = Protocol_ID_CC;
01333             } 
01334             else if(*it == Action_ID_CC_FD){
01335                if(parameter_.verbose_) std::cout << "Add facet defining cycle constraints: " << std::flush;     
01336                n = findCycleConstraints(constraint, true, false);
01337                cycleConstraints=n;
01338                if(parameter_.verbose_) std::cout  << n << std::endl; 
01339                protocol_ID = Protocol_ID_CC;
01340             } 
01341             else if(*it == Action_ID_CC_FDB){
01342                if(parameter_.verbose_) std::cout << "Add facet defining cycle constraints (with bounding): " << std::flush;     
01343                n = findCycleConstraints(constraint, true, true);
01344                cycleConstraints=n;
01345                if(parameter_.verbose_) std::cout  << n << std::endl; 
01346                protocol_ID = Protocol_ID_CC;
01347             }
01348             else if(*it == Action_ID_CC_B){
01349                if(parameter_.verbose_) std::cout << "Add cycle constraints (with bounding): " << std::flush;     
01350                n = findCycleConstraints(constraint, false, true);
01351                cycleConstraints=n;
01352                if(parameter_.verbose_) std::cout  << n << std::endl; 
01353                protocol_ID = Protocol_ID_CC;
01354             } 
01355             else  if(*it == Action_ID_RemoveConstraints){ 
01356                if(parameter_.verbose_) std::cout << "Remove unused constraints: " << std::flush;            
01357                n = removeUnusedConstraints();
01358                if(parameter_.verbose_) std::cout  << n  << std::endl; 
01359                protocol_ID = Protocol_ID_RemoveConstraints;  
01360             }
01361             else  if(*it == Action_ID_IntegerConstraints && !integerMode_){
01362                if(parameter_.verbose_) std::cout << "Add  integer constraints: " << std::flush;
01363                n = enforceIntegerConstraints();
01364                if(parameter_.verbose_) std::cout  << n << std::endl; 
01365                protocol_ID = Protocol_ID_IntegerConstraints;  
01366             } 
01367             else  if(*it == Action_ID_OWC){
01368                if(cycleConstraints== std::numeric_limits<size_t>::max()){
01369                   std::cout << "WARNING: using Odd Wheel Contraints without Cycle Constrains! -> Use CC,OWC!"<<std::endl;
01370                   n=0;
01371                }
01372                else if(cycleConstraints==0){             
01373                   if(parameter_.verbose_) std::cout << "Add odd wheel constraints: " << std::flush;
01374                   n = findOddWheelConstraints(constraint);
01375                   if(parameter_.verbose_) std::cout  << n << std::endl;
01376                }
01377                else{
01378                   //since cycle constraints are found we have to search for more violated cycle constraints first
01379                }
01380                protocol_ID = Protocol_ID_OWC;  
01381             }
01382             else{
01383                std::cout <<"Unknown Inference State "<<*it<<std::endl;
01384             } 
01385             timer2.toc();
01386             T[protocol_ID] += timer2.elapsedTime();
01387             C[protocol_ID] += n;
01388             if(n>0) constraintAdded = true;
01389          }
01390          //std::cout <<"... done!"<<std::endl;
01391          
01392        
01393          
01394          if(!constraintAdded){
01395             //Switch to next working state
01396             ++workingState;
01397             if(workingState<workFlow_.size())
01398                if(parameter_.verbose_) std::cout <<std::endl<< "** Switching into next state ( "<< workingState << " )**" << std::endl;
01399             break;
01400          }
01401          else{
01402             timer2.tic();
01403             //Add Constraints
01404             model_.add(constraint);
01405             //cplex_.addCuts(constraint);
01406             timer2.toc();
01407             T[Protocol_ID_AddConstraints] += timer2.elapsedTime();
01408          }
01409          
01410          // Check for timeout
01411          timer.toc();
01412          if(timer.elapsedTime()>parameter_.timeOut_) {
01413             break;
01414          }
01415          
01416       } //end inner loop over one working state
01417    } //end loop over all working states
01418    
01419    mcv.end(*this); 
01420    if(parameter_.verbose_){
01421       std::cout << "end normal"<<std::endl;
01422       std::cout <<"Protokoll:"<<std::endl;
01423       std::cout <<"=========="<<std::endl;
01424       std::cout << "  i  |   SOLVE  |   ADD    |    CC    |    OWC   |    TTC   |    MTV   |     IC    " <<std::endl;
01425       std::cout << "-----+----------+----------+----------+----------+----------+----------+-----------" <<std::endl;
01426    }
01427    std::vector<size_t> IDS;
01428    IDS.push_back(Protocol_ID_Solve);
01429    IDS.push_back(Protocol_ID_AddConstraints);
01430    IDS.push_back(Protocol_ID_CC);
01431    IDS.push_back(Protocol_ID_OWC);
01432    IDS.push_back(Protocol_ID_TTC);
01433    IDS.push_back(Protocol_ID_MTC);
01434    IDS.push_back(Protocol_ID_IntegerConstraints);
01435  
01436    if(parameter_.verbose_){
01437       for(size_t i=0; i<protocolateTiming_.size(); ++i){
01438          std::cout << setw(5)<<   i  ;
01439          for(size_t n=0; n<IDS.size(); ++n){
01440             std::cout << "|"<< setw(10) << setiosflags(ios::fixed)<< setprecision(4) << protocolateConstraints_[i][IDS[n]];
01441          }
01442          std::cout << std::endl; 
01443          std::cout << "     "  ; 
01444          for(size_t n=0; n<IDS.size(); ++n){ 
01445             std::cout << "|"<< setw(10) << setiosflags(ios::fixed)<< setprecision(4) << protocolateTiming_[i][IDS[n]];
01446          }
01447          std::cout << std::endl;
01448          std::cout << "-----+----------+----------+----------+----------+----------+----------+-----------" <<std::endl;
01449       }
01450       std::cout << "sum  ";
01451       double t_all=0;
01452       for(size_t n=0; n<IDS.size(); ++n){
01453          double t_one=0;
01454          for(size_t i=0; i<protocolateTiming_.size(); ++i){
01455             t_one += protocolateTiming_[i][IDS[n]];
01456          }
01457          std::cout << "|"<< setw(10) << setiosflags(ios::fixed)<< setprecision(4) << t_one;
01458          t_all += t_one;
01459       }
01460       std::cout << " | " <<t_all <<std::endl;
01461       std::cout << "-----+----------+----------+----------+----------+----------+----------+-----------" <<std::endl;
01462    }
01463    return NORMAL;
01464 }
01465 
01466 template <class GM, class ACC>
01467 InferenceTermination
01468 Multicut<GM,ACC>::arg
01469 (
01470    std::vector<typename Multicut<GM,ACC>::LabelType>& x,
01471    const size_t N
01472    ) const
01473 {
01474    if(N!=1) {
01475       return UNKNOWN;
01476    }
01477    else{
01478       if(problemType_ == MWC) {
01479          if(parameter_.MWCRounding_== parameter_.NEAREST){
01480             x.resize(gm_.numberOfVariables());
01481             for(IndexType node = 0; node<gm_.numberOfVariables(); ++node) {
01482                double v = sol_[numberOfTerminals_*node+0];
01483                x[node] = 0;
01484                for(LabelType i=0; i<gm_.numberOfLabels(node); ++i) {
01485                   if(sol_[numberOfTerminals_*node+i]<v) {
01486                      x[node]=i;
01487                   }
01488                }
01489             }
01490             return NORMAL;
01491          }
01492          else if(parameter_.MWCRounding_==parameter_.DERANDOMIZED){
01493             return derandomizedRounding(x);
01494          }
01495          else if(parameter_.MWCRounding_==parameter_.PSEUDODERANDOMIZED){
01496             return pseudoDerandomizedRounding(x,1000);
01497          }
01498          else{
01499             return UNKNOWN;
01500          }
01501       }
01502       else{
01503          std::vector<std::list<size_t> > neighbours0;
01504          InferenceTermination r =  partition(x, neighbours0,parameter_.edgeRoundingValue_);
01505          return r;
01506       }
01507    }
01508 }
01509 
01510 
01511 template <class GM, class ACC>
01512 InferenceTermination
01513 Multicut<GM,ACC>::pseudoDerandomizedRounding
01514 (
01515    std::vector<typename Multicut<GM,ACC>::LabelType>& x,
01516    size_t bins = 1000
01517    ) const
01518 {
01519    std::vector<bool>      processedBins(bins+1,false);
01520    std::vector<LabelType> temp;
01521    double                 value = 1000000000000.0;
01522    std::vector<LabelType> labelorder1(numberOfTerminals_,numberOfTerminals_-1);
01523    std::vector<LabelType> labelorder2(numberOfTerminals_,numberOfTerminals_-1);
01524    for(LabelType i=0; i<numberOfTerminals_-1;++i){
01525       labelorder1[i]=i;
01526       labelorder2[i]=numberOfTerminals_-2-i;
01527    } 
01528    for(size_t i=0; i<numberOfTerminals_*gm_.numberOfVariables();++i){
01529       size_t bin;
01530       double t,d;
01531       if(sol_[i]<=0){
01532          bin=0;
01533          t=0;
01534       }
01535       else if(sol_[i]>=1){
01536          bin=bins;
01537          t=1;
01538       }
01539       else{
01540          bin = (size_t)(sol_[i]*bins)%bins;
01541          t = sol_[i];
01542       }
01543       if(!processedBins[bin]){
01544          processedBins[bin]=true;
01545          if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder1,sol_[i]))){
01546             value=d;
01547             x=temp;
01548          }
01549          if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder2,sol_[i]))){
01550             value=d;
01551             x=temp;
01552          }
01553       }
01554    }
01555    return NORMAL;
01556 }
01557 
01558 template <class GM, class ACC>
01559 InferenceTermination
01560 Multicut<GM,ACC>::derandomizedRounding
01561 (
01562    std::vector<typename Multicut<GM,ACC>::LabelType>& x
01563    ) const
01564 {
01565    std::vector<LabelType> temp;
01566    double                 value = 1000000000000.0;
01567    std::vector<LabelType> labelorder1(numberOfTerminals_,numberOfTerminals_-1);
01568    std::vector<LabelType> labelorder2(numberOfTerminals_,numberOfTerminals_-1);
01569    for(LabelType i=0; i<numberOfTerminals_-1;++i){
01570       labelorder1[i]=i;
01571       labelorder2[i]=numberOfTerminals_-2-i;
01572    }
01573    // Test primitives
01574    double d;
01575    if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder1,1e-8))){
01576       value=d;
01577       x=temp;
01578    }
01579    if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder2,1e-8))){
01580       value=d;
01581       x=temp;
01582    } 
01583    if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder1,1-1e-8))){
01584       value=d;
01585       x=temp;
01586    }
01587    if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder2,1-1e-8))){
01588       value=d;
01589       x=temp;
01590    }
01591    for(size_t i=0; i<numberOfTerminals_*gm_.numberOfVariables();++i){
01592       if( sol_[i]>1e-8 &&  sol_[i]<1-1e-8){
01593          if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder1,sol_[i]))){
01594             value=d;
01595             x=temp;
01596          }
01597          if(value>(d=derandomizedRoundingSubProcedure(temp,labelorder2,sol_[i]))){
01598             value=d;
01599             x=temp;
01600          }
01601       }
01602    }
01603    return NORMAL;
01604 }
01605 
01606 template <class GM, class ACC>
01607 double
01608 Multicut<GM,ACC>::derandomizedRoundingSubProcedure
01609 (
01610    std::vector<typename Multicut<GM,ACC>::LabelType>& x,
01611    const std::vector<typename Multicut<GM,ACC>::LabelType>& labelorder,
01612    const double threshold
01613    ) const
01614 { 
01615    const LabelType lastLabel = labelorder.back();
01616    const IndexType numVar    = gm_.numberOfVariables();
01617 
01618    x.assign(numVar,lastLabel);
01619   
01620    for(size_t i=0; i<labelorder.size()-1; ++i){
01621       for(IndexType v=0; v<numVar; ++v){
01622          if(x[v]==lastLabel && sol_[numberOfTerminals_*v+i]<=threshold){
01623             x[v]=labelorder[i];
01624          }
01625       }
01626    }
01627    return gm_.evaluate(x);
01628 }
01629 
01630 
01631 
01632 
01633 template <class GM, class ACC>
01634 InferenceTermination
01635 Multicut<GM,ACC>::partition
01636 (
01637    std::vector<LabelType>& partit,
01638    std::vector<std::list<size_t> >& neighbours0,
01639    double threshold = 0.5
01640    ) const
01641 {
01642 
01643    partit.resize(numberOfNodes_,0);
01644    neighbours0.resize(numberOfNodes_, std::list<size_t>());
01645 
01646    size_t counter=0;
01647    for(size_t i=0; i<numberOfInternalEdges_; ++i) {
01648       IndexType u = edgeNodes_[i].first;//variableIndex(0);
01649       IndexType v = edgeNodes_[i].second;//variableIndex(1);
01650       if(sol_[numberOfTerminalEdges_+counter] <= threshold) {
01651          neighbours0[u].push_back(v);
01652          neighbours0[v].push_back(u);
01653       }
01654       ++counter;
01655    }
01656 
01657    LabelType p=0;
01658    std::vector<bool> assigned(numberOfNodes_,false);
01659    for(size_t node=0; node<numberOfNodes_; ++node) {
01660       if(assigned[node])
01661          continue;
01662       else{
01663          std::list<size_t> nodeList;
01664          partit[node]   = p;
01665          assigned[node] = true;
01666          nodeList.push_back(node);
01667          while(!nodeList.empty()) {
01668             size_t n=nodeList.front(); nodeList.pop_front();
01669             std::list<size_t>::const_iterator it;
01670             for(it=neighbours0[n].begin() ; it != neighbours0[n].end(); ++it) {
01671                if(!assigned[*it]) {
01672                   partit[*it] = p;
01673                   assigned[*it] = true;
01674                   nodeList.push_back(*it);
01675                }
01676             }
01677          }
01678          ++p;
01679       }
01680    }
01681    return NORMAL;
01682 }
01683 
01684 
01685 template <class GM, class ACC>
01686 typename Multicut<GM,ACC>::ValueType
01687 Multicut<GM,ACC>::evaluate
01688 (
01689    std::vector<LabelType>& conf
01690    ) const
01691 {
01692 
01693    return gm_.evaluate(conf);
01694 }
01695 
01696 template<class GM, class ACC>
01697 inline const typename Multicut<GM, ACC>::GraphicalModelType&
01698 Multicut<GM, ACC>::graphicalModel() const
01699 {
01700    return gm_;
01701 }
01702 
01703 template<class GM, class ACC>
01704 typename GM::ValueType Multicut<GM, ACC>::bound() const
01705 {
01706    return bound_;
01707 }
01708 
01709 template<class GM, class ACC>
01710 typename GM::ValueType Multicut<GM, ACC>::value() const
01711 {
01712    std::vector<LabelType> c;
01713    arg(c);  
01714    ValueType value = gm_.evaluate(c);
01715    return value;
01716 }
01717 
01718 template<class GM, class ACC>
01719 bool Multicut<GM, ACC>::readWorkFlow(std::string s)
01720 {
01721    if(s[0]!='(' || s[s.size()-1] !=')')
01722       return false;
01723    workFlow_.clear();
01724    size_t n=0;
01725    std::string sepString;
01726    if(s.size()<2)
01727       return false;
01728    while(n<s.size()){
01729       if(s[n]==',' || s[n]==')'){//End of sepString
01730          if(sepString.compare("CC")==0)
01731             workFlow_.back().push_back(Action_ID_CC);
01732          else if(sepString.compare("CC-I")==0)
01733             workFlow_.back().push_back(Action_ID_CC_I);
01734          else if(sepString.compare("CC-IFD")==0)
01735             workFlow_.back().push_back(Action_ID_CC_IFD);
01736          else if(sepString.compare("CC-B")==0)
01737             workFlow_.back().push_back(Action_ID_CC_B);
01738          else if(sepString.compare("CC-FDB")==0)
01739             workFlow_.back().push_back(Action_ID_CC_FDB);
01740          else if(sepString.compare("CC-FD")==0)
01741             workFlow_.back().push_back(Action_ID_CC_FD);
01742          else if(sepString.compare("TTC")==0)
01743             workFlow_.back().push_back(Action_ID_TTC);
01744          else if(sepString.compare("TTC-I")==0)
01745             workFlow_.back().push_back(Action_ID_TTC_I);
01746          else if(sepString.compare("MTC")==0)
01747             workFlow_.back().push_back(Action_ID_MTC);
01748          else if(sepString.compare("OWC")==0)
01749             workFlow_.back().push_back(Action_ID_OWC);
01750          else if(sepString.compare("IC")==0)
01751             workFlow_.back().push_back(Action_ID_IntegerConstraints);
01752          else
01753             std::cout << "WARNING:  Unknown Seperation Procedure ' "<<sepString<<"' is skipped!"<<std::endl;
01754          sepString.clear();
01755       }
01756       else if(s[n]=='('){//New Round
01757          workFlow_.push_back(std::vector<size_t>()); 
01758       }
01759       else{
01760          sepString += s[n];
01761       }
01762       ++n;
01763    }
01764    return true;
01765 }
01766   
01767 
01773 template<class GM, class ACC>
01774 template<class DOUBLEVECTOR>
01775 inline double Multicut<GM, ACC>::shortestPath(
01776    const IndexType startNode, 
01777    const IndexType endNode, 
01778    const std::vector<EdgeMapType >& E, //E[n][i].first/.second are the i-th neighbored node and weight-index (for w), respectively. 
01779    const DOUBLEVECTOR& w,
01780    std::vector<IndexType>& shortestPath,
01781    const double maxLength = std::numeric_limits<double>::infinity(),
01782    bool cordless = true
01783 ) const
01784 { 
01785    
01786    const IndexType numberOfNodes = E.size();
01787    const double    inf           = std::numeric_limits<double>::infinity();
01788    const IndexType nonePrev      = endNode;
01789 
01790    std::vector<IndexType>  prev(numberOfNodes,nonePrev);
01791    std::vector<double>     dist(numberOfNodes,inf);
01792    MYSET                   openNodes;
01793    
01794    openNodes.insert(startNode);
01795    dist[startNode]=0.0;
01796 
01797    while(!openNodes.empty()){ 
01798       IndexType node;
01799       //Find smallest open node
01800       {
01801          typename MYSET::iterator it, itMin;
01802          double v = std::numeric_limits<double>::infinity();
01803          for(it = openNodes.begin(); it!= openNodes.end(); ++it){
01804             if( dist[*it]<v ){
01805                v = dist[*it];
01806                itMin = it;
01807             }
01808          }
01809          node = *itMin;
01810          openNodes.erase(itMin);
01811       }
01812       // Check if target is reached
01813       if(node == endNode)
01814          break;
01815       // Update all neigbors of node
01816       {
01817          typename EdgeMapType::const_iterator it;
01818          for(it=E[node].begin() ; it != E[node].end(); ++it) {
01819             const IndexType node2      = (*it).first;  //second edge-node
01820             const LPIndexType weighId  = (*it).second; //index in weigh-vector w
01821             double cuttedWeight        = max(0.0,w[weighId]); //cut up negative edge-weights
01822             const double weight2       = dist[node]+cuttedWeight;
01823            
01824 
01825             if(dist[node2] > weight2 && weight2 < maxLength){
01826                //check chordality
01827                bool updateNode = true;
01828                if(cordless) {
01829                   IndexType s = node;
01830                   while(s!=startNode){
01831                      s= prev[s];
01832                      if(s==startNode && node2==endNode) continue;
01833                      if(neighbours[node2].find(s)!=neighbours[node2].end()) {
01834                         updateNode = false; // do not update node if path is chordal
01835                         break;
01836                      } 
01837                   }
01838                } 
01839                if(updateNode){
01840                   prev[node2] = node;
01841                   dist[node2] = weight2;
01842                   openNodes.insert(node2);
01843                } 
01844             }
01845          }
01846       }
01847    }
01848    
01849    if(prev[endNode] != nonePrev){//find path?
01850       shortestPath.clear();
01851       shortestPath.push_back(endNode);
01852       IndexType n = endNode;
01853       do{
01854          n=prev[n];
01855          shortestPath.push_back(n);
01856       }while(n!=startNode);
01857       OPENGM_ASSERT(shortestPath.back() == startNode);
01858    }
01859    
01860    return dist[endNode];
01861 }
01862 
01863 
01864 template<class GM, class ACC>
01865 std::vector<double>
01866 Multicut<GM, ACC>::getEdgeLabeling
01867 () const
01868 {
01869    std::vector<double> l(numberOfInternalEdges_,0);
01870    for(size_t i=0; i<numberOfInternalEdges_; ++i) {
01871       l[i] = sol_[numberOfTerminalEdges_+i];
01872    }
01873    return l;
01874 }
01875 
01876 // WARNING: this function is considered experimental.
01877 // variable indices refer to variables of the LP set up
01878 // in the constructor of the class template LPCplex,
01879 // NOT to the variables of the graphical model.
01880 template<class GM, class ACC>
01881 template<class LPVariableIndexIterator, class CoefficientIterator>
01882 void Multicut<GM, ACC>::addConstraint
01883 (
01884    LPVariableIndexIterator viBegin,
01885    LPVariableIndexIterator viEnd,
01886    CoefficientIterator coefficient,
01887    const ValueType& lowerBound,
01888    const ValueType& upperBound)
01889 {
01890    IloRange constraint(env_, lowerBound, upperBound);
01891    while(viBegin != viEnd) {
01892       constraint.setLinearCoef(x_[*viBegin], *coefficient);
01893       ++viBegin;
01894       ++coefficient;
01895    }
01896    model_.add(constraint);
01897    // this update of model_ does not require a
01898    // re-initialization of the object cplex_.
01899    // cplex_ is initialized in the constructor.
01900 }
01901 
01902 } // end namespace opengm
01903 
01904 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:05 2013 for OpenGM by  doxygen 1.6.3