2 #ifndef OPENGM_PARTITIONMOVE_HXX 3 #define OPENGM_PARTITIONMOVE_HXX 15 #include <boost/unordered_map.hpp> 16 #include <boost/unordered_set.hpp> 18 #include <ext/hash_map> 19 #include <ext/hash_set> 38 template<
class GM,
class ACC>
50 typedef boost::unordered_map<IndexType, LPIndexType>
EdgeMapType;
53 typedef __gnu_cxx::hash_map<IndexType, LPIndexType>
EdgeMapType;
63 template<
class _GM,
class _ACC>
77 virtual std::string
name()
const {
return "PartitionMove";}
84 enum ProblemType {INVALID, MC, MWC};
86 const GraphicalModelType& gm_;
87 ProblemType problemType_;
91 LPIndexType numberOfInternalEdges_;
96 std::vector<EdgeMapType > neighbours_;
97 std::vector<double> edgeWeight_;
99 std::vector<LabelType> states_;
102 double solveBinaryKL(VariableSetType&, VariableSetType&);
107 template<
class GM,
class ACC>
112 template<
class GM,
class ACC>
117 ) : gm_(gm), parameter_(para)
120 throw RuntimeError(
"This implementation does only supports Min-Plus-Semiring.");
126 numberOfInternalEdges_ = 0;
127 numberOfTerminals_ = gm_.numberOfLabels(0);
128 for(
size_t i=0; i<gm_.numberOfVariables(); ++i){
129 if(gm_.numberOfLabels(i)<gm_.numberOfVariables()) {
131 numberOfTerminals_ = std::max(numberOfTerminals_ ,gm_.numberOfLabels(i));
134 for(
size_t f=0; f<gm_.numberOfFactors();++f) {
135 if(gm_[f].numberOfVariables()==0) {
138 else if(gm_[f].numberOfVariables()==1) {
141 else if(gm_[f].numberOfVariables()==2) {
142 ++numberOfInternalEdges_;
143 if(!gm_[f].isPotts()) {
144 problemType_ = INVALID;
149 problemType_ = INVALID;
154 if(problemType_ == INVALID)
155 throw RuntimeError(
"Invalid Model for Multicut-Solver! Solver requires a potts model!");
156 if(problemType_ == MWC)
157 throw RuntimeError(
"Invalid Model for Multicut-Solver! Solver currently do not support first order terms!");
161 neighbours_.resize(gm_.numberOfVariables());
162 edgeWeight_.resize(numberOfInternalEdges_,0);
166 for(
size_t f=0; f<gm_.numberOfFactors(); ++f) {
167 if(gm_[f].numberOfVariables()==0) {
169 constant_+=gm_[f](&l);
171 else if(gm_[f].numberOfVariables()==2) {
174 edgeWeight_[numberOfInternalEdges] += gm_[f](cc1) - gm_[f](cc0);
175 constant_ += gm_[f](cc0);
178 neighbours_[u][v] = numberOfInternalEdges;
179 neighbours_[v][u] = numberOfInternalEdges;
180 ++numberOfInternalEdges;
183 throw RuntimeError(
"Only supports second order Potts functions!");
186 OPENGM_ASSERT(numberOfInternalEdges==numberOfInternalEdges_);
188 states_.resize(gm_.numberOfVariables(),0);
192 for(
size_t i=0; i<states_.size();++i){
193 states_[i]=rand()%10;
199 std::vector<bool> assigned(states_.size(),
false);
200 for(
IndexType node=0; node<states_.size(); ++node) {
204 std::list<IndexType> nodeList;
206 assigned[node] =
true;
207 nodeList.push_back(node);
208 while(!nodeList.empty()) {
209 size_t n=nodeList.front(); nodeList.pop_front();
210 for(
typename EdgeMapType::const_iterator it=neighbours_[n].begin() ; it != neighbours_[n].end(); ++it) {
212 if(!assigned[node2] && edgeWeight_[(*it).second]>0) {
214 assigned[node2] =
true;
215 nodeList.push_back(node2);
225 for(
size_t i=0; i<states_.size();++i){
234 template <
class GM,
class ACC>
239 return infer(visitor);
243 template <
class GM,
class ACC>
244 template<
class VisitorType>
248 visitor.begin(*
this);
254 template <
class GM,
class ACC>
255 template<
class VisitorType>
260 std::vector<VariableSetType> partitionSets;
264 for(
size_t i=0; i<states_.size(); ++i)
265 if(states_[i]+1>numberOfPartitions) numberOfPartitions=states_[i]+1;
266 partitionSets.resize(numberOfPartitions);
267 for(
IndexType i=0; i<states_.size(); ++i){
268 partitionSets[states_[i]].insert(i);
275 std::vector<size_t> pruneSets;
277 for(
size_t part0=0; part0<numberOfPartitions; ++part0){
280 std::set<size_t> neighbordSets;
281 for(
typename VariableSetType::const_iterator it=partitionSets[part0].begin(); it!=partitionSets[part0].end(); ++it){
283 for(
typename EdgeMapType::const_iterator nit=neighbours_[node].begin() ; nit != neighbours_[node].end(); ++nit) {
285 if(states_[node2]>part0){
286 neighbordSets.insert(states_[node2]);
290 for(std::set<size_t>::const_iterator it=neighbordSets.begin(); it!=neighbordSets.end();++it){
293 if(partitionSets[part0].size()==0 || partitionSets[part1].size()==0)
295 double improvement = solveBinaryKL(partitionSets[part0],partitionSets[part1]);
298 if(-1e-8>improvement){
304 for(
size_t part0=0; part0<numberOfPartitions; ++part0){
306 if(partitionSets[part0].size()==0){
308 pruneSets.push_back(part0);
311 else if(partitionSets[part0].size()>1){
315 double improvement = solveBinaryKL(partitionSets[part0], emptySet);
316 if(emptySet.size()>0){
318 partitionSets.push_back(emptySet);
325 for(
size_t i=0; i<pruneSets.size(); ++i){
326 size_t part = pruneSets[pruneSets.size()-1-i];
327 partitionSets.erase( partitionSets.begin()+part);
330 numberOfPartitions = partitionSets.size();
331 for(
size_t part=0; part<numberOfPartitions; ++part){
332 for(
typename VariableSetType::const_iterator it=partitionSets[part].begin(); it!=partitionSets[part].end(); ++it){
343 template <
class GM,
class ACC>
350 double improvement = 0.0;
353 for(
size_t outerIt=0; outerIt<100;++outerIt){
355 std::vector<double> D(gm_.numberOfVariables(),0);
356 for(
typename VariableSetType::const_iterator it=set0.begin(); it!=set0.end(); ++it){
360 for (
typename EdgeMapType::const_iterator eit=neighbours_[node].begin(); eit!=neighbours_[node].end(); ++eit){
362 const double weight = edgeWeight_[(*eit).second];
364 if (set0.find(node2) != set0.end()) {
367 else if(set1.find(node2) != set1.end()){
371 D[node] = -(E_a - I_a);
373 for(
typename VariableSetType::const_iterator it=set1.begin(); it!=set1.end(); ++it){
377 for(
typename EdgeMapType::const_iterator eit=neighbours_[node].begin(); eit!=neighbours_[node].end(); ++eit){
379 const double weight = edgeWeight_[(*eit).second];
381 if (set1.find(node2) != set1.end()) {
384 else if(set0.find(node2) != set0.end()){
388 D[node] = -(E_a - I_a);
392 for(
size_t i=0; i<D.size(); ++i){
399 std::vector<bool> isMovedNode(gm_.numberOfVariables(),
false);
400 std::vector<IndexType> nodeSequence;
401 std::vector<double> improveSequence;
402 std::vector<double> improveSumSequence(1,0.0);
406 for(
size_t innerIt=0; innerIt<1000; ++innerIt){
407 double improve = std::numeric_limits<double>::infinity();
411 for(
typename VariableSetType::const_iterator it=set0.begin(); it!=set0.end(); ++it){
412 if(isMovedNode[*it]){
424 for(
typename VariableSetType::const_iterator it=set1.begin(); it!=set1.end(); ++it){
425 if(isMovedNode[*it]){
444 isMovedNode[node]=
true;
445 nodeSequence.push_back(node);
446 improveSumSequence.push_back(improveSumSequence.back()+improve);
447 improveSequence.push_back(improve);
448 if (improveSumSequence[bestMove]>improveSumSequence.back()) {
449 bestMove = improveSumSequence.size()-1;
453 for(
typename EdgeMapType::const_iterator eit=neighbours_[node].begin(); eit!=neighbours_[node].end(); ++eit){
455 double weight = edgeWeight_[(*eit).second];
456 if(mySet.find(node2) != mySet.end()){
457 D[node2] -= 2.0 * weight;
460 D[node2] += 2.0 * weight;
467 if(improveSumSequence[bestMove]>-1e-10)
470 improvement += improveSumSequence[bestMove];
471 for (
size_t i = 0; i < bestMove; ++i) {
472 int node = nodeSequence[i];
473 if (set0.find(node) != set0.end()) {
488 template <
class GM,
class ACC>
500 x.resize(gm_.numberOfVariables());
501 for(
size_t i=0; i<gm_.numberOfVariables(); ++i)
PartitionMove(const GraphicalModelType &, Parameter para=Parameter())
PartitionMove< _GM, ACC > type
visitors::TimingVisitor< PartitionMove< GM, ACC > > TimingVisitorType
Addition as a binary operation.
PartitionMove< _GM, _ACC > type
#define OPENGM_ASSERT(expression)
virtual std::string name() const
GraphicalModelType::OperatorType OperatorType
__gnu_cxx::hash_set< IndexType > VariableSetType
const GraphicalModelType & graphicalModel() const
visitors::EmptyVisitor< PartitionMove< GM, ACC > > EmptyVisitorType
GraphicalModelType::IndexType IndexType
__gnu_cxx::hash_map< IndexType, LPIndexType > EdgeMapType
visitors::VerboseVisitor< PartitionMove< GM, ACC > > VerboseVisitorType
Inference algorithm interface.
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
virtual InferenceTermination infer()
GraphicalModelType::LabelType LabelType
Minimization as a unary accumulation.
static const size_t ContinueInf
Partition Move Currently Partition Move only implements the Kernighan-Lin-Algorithm.