contrib/mul/mmn/mmn_dp_solver.h
Go to the documentation of this file.
00001 #ifndef mmn_dp_solver_h_
00002 #define mmn_dp_solver_h_
00003 //:
00004 // \file
00005 // \brief Solve restricted class of Markov problems (trees and tri-trees)
00006 // \author Tim Cootes
00007 
00008 #include <mmn/mmn_arc.h>
00009 #include <mmn/mmn_dependancy.h>
00010 #include <mmn/mmn_solver.h>
00011 #include <vnl/vnl_vector.h>
00012 #include <vnl/vnl_matrix.h>
00013 #include <vil/vil_image_view.h>
00014 #include <vcl_vector.h>
00015 #include <vcl_iosfwd.h>
00016 
00017 //: Solve restricted class of Markov problems (trees and tri-trees)
00018 //  Find choice of values at each node which minimises Markov problem.
00019 //  Minimises F() = sum node_costs + sum pair_costs
00020 //
00021 //  Assumes graph defining relationships can be fully decomposed by
00022 //  repeatedly removing any nodes with two or fewer neighbours.
00023 //  Global optimum is found using a series of sequential exhaustive
00024 //  optimisations.
00025 class mmn_dp_solver : public mmn_solver
00026 {
00027  private:
00028   //: Workspace for incremental costs of each node
00029   vcl_vector<vnl_vector<double> > nc_;
00030 
00031   //: Workspace for incremental costs of each arc
00032   vcl_vector<vnl_matrix<double> > pc_;
00033 
00034   //: index1[i][j] = optimal choice for i if other node is j
00035   vcl_vector<vcl_vector<unsigned> > index1_;
00036 
00037   //: index2[i](j,k) = optimal choice of i if two other nodes are (j,k)
00038   vcl_vector<vnl_matrix<int> > index2_;
00039 
00040   //: Dependencies
00041   vcl_vector<mmn_dependancy> deps_;
00042 
00043   //: Compute optimal choice for node dep.v0 for each possible v1
00044   //  Uses pair costs for v0-v1 (in pc_) and the node cost nc_(v0)
00045   void process_dep1(const mmn_dependancy& dep);
00046 
00047   //: Compute optimal choice for dep.v0 given v1 and v2
00048   //  Uses only pairwise and node costs (in nc_ and pc_)
00049   void process_dep2(const mmn_dependancy& dep);
00050 
00051   //: Compute optimal choice for dep.v0 given v1 and v2
00052   //  Includes cost depending on (v0,v1,v2) as well as pairwise and
00053   //  node costs.
00054   // tri_cost(i,j,k) is cost of associating smallest node index
00055   // with i, next with j and largest node index with k.
00056   void process_dep2t(const mmn_dependancy& dep,
00057                     const vil_image_view<double>& tri_cost);
00058 
00059  public:
00060   //: Default constructor
00061   mmn_dp_solver();
00062 
00063   //: Index of root node
00064   unsigned root() const;
00065 
00066   //: Input the arcs that define the graph
00067   virtual void set_arcs(unsigned num_nodes,
00068                         const vcl_vector<mmn_arc>& arcs);
00069 
00070   //: Define dependencies
00071   void set_dependancies(const vcl_vector<mmn_dependancy>& deps,
00072                         unsigned n_nodes, unsigned max_n_arcs);
00073 
00074   //: Read access to dependencies
00075   const vcl_vector<mmn_dependancy>& deps() const { return deps_; }
00076 
00077   //: Find values for each node with minimise the total cost
00078   //  \param node_cost: node_cost[i][j] is cost of selecting value j for node i
00079   //  \param pair_cost: pair_cost[a](i,j) is cost of selecting values (i,j) for nodes at end of arc a.
00080   //  \param x: On exit, x[i] gives choice for node i
00081   // NOTE: If arc a connects nodes v1,v2, the associated pair_cost is ordered
00082   // with the node with the lowest index being the first parameter.  Thus if
00083   // v1 has value i1, v2 has value i2, then the cost of this choice is
00084   // (v1<v2?pair_cost(i1,i2):pair_cost(i2,i1))
00085   // Returns the minimum cost
00086   virtual double solve(const vcl_vector<vnl_vector<double> >& node_cost,
00087                  const vcl_vector<vnl_matrix<double> >& pair_cost,
00088                  vcl_vector<unsigned>& x);
00089 
00090   //: Find values for each node with minimise the total cost
00091   //  As solve(node_cost,pair_cost,x), but allows inclusion of
00092   //  costs for triplets (ie when v0 depends on v1 and v2).
00093   //  tri_cost(i,j,k) gives cost of node min(v0,v1,v2) being
00094   //  value i, node mid(v0,v1,v2) being value j and
00095   //  node max(v0,v1,v2) being value k.
00096   double solve(const vcl_vector<vnl_vector<double> >& node_cost,
00097                  const vcl_vector<vnl_matrix<double> >& pair_cost,
00098                  const vcl_vector<vil_image_view<double> >& tri_cost,
00099                  vcl_vector<unsigned>& x);
00100 
00101   //: Compute optimal values for x[i] given that root node is root_value
00102   //  Assumes that solve() has been already called.
00103   void backtrace(unsigned root_value,vcl_vector<unsigned>& x);
00104 
00105   //: root_cost()[i] is cost of selecting value i for the root node
00106   const vnl_vector<double>& root_cost() const { return nc_[root()]; }
00107 
00108   //: Initialise from a text stream
00109   virtual bool set_from_stream(vcl_istream &is);
00110 
00111   //: Version number for I/O
00112   short version_no() const;
00113 
00114   //: Name of the class
00115   virtual vcl_string is_a() const;
00116 
00117   //: Create a copy on the heap and return base class pointer
00118   virtual mmn_solver* clone() const;
00119 
00120   //: Print class to os
00121   virtual void print_summary(vcl_ostream& os) const;
00122 
00123   //: Save class to binary file stream
00124   virtual void b_write(vsl_b_ostream& bfs) const;
00125 
00126   //: Load class from binary file stream
00127   virtual void b_read(vsl_b_istream& bfs);
00128 };
00129 
00130 #endif // mmn_dp_solver_h_