// Copyright (C) 2011 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_FIND_MAX_FACTOR_GRAPH_nMPLP_ABSTRACT_Hh_ #ifdef DLIB_FIND_MAX_FACTOR_GRAPH_nMPLP_ABSTRACT_Hh_ #include <vector> namespace dlib { // ---------------------------------------------------------------------------------------- class map_problem { /*! WHAT THIS OBJECT REPRESENTS This object represents a factor graph or graphical model. In particular, this object defines the interface a MAP problem on a factor graph must implement if it is to be solved using the find_max_factor_graph_nmplp() routine defined at the bottom of this file. Note that there is no dlib::map_problem object. What you are looking at here is simply the interface definition for a map problem. You must implement your own version of this object for the problem you wish to solve and then pass it to the find_max_factor_graph_nmplp() routine. Note also that a factor graph should not have any nodes which are neighbors with themselves. Additionally, the graph is undirected. This mean that if A is a neighbor of B then B must be a neighbor of A for the map problem to be valid. Finally, note that the "neighbor" relationship between nodes means the following: Two nodes are neighbors if and only if there is a potential function (implemented by the factor_value() method) which operates on the nodes. !*/ public: class node_iterator { /*! WHAT THIS OBJECT REPRESENTS This is a simple forward iterator for iterating over the nodes/variables in this factor graph. Note that you can't dereference the iterator and obtain a value. That is, the iterator is opaque to the user. It is used only as an argument to the other methods defined in this interface. !*/ public: node_iterator( ); /*! ensures - constructs an iterator in an undefined state !*/ node_iterator( const node_iterator& item ); /*! ensures - #*this is a copy of item !*/ node_iterator& operator= ( const node_iterator& item ); /*! ensures - #*this is a copy of item - returns #*this !*/ bool operator== ( const node_iterator& item ) const; /*! ensures - returns true if *this and item both reference the same node in the factor graph and false otherwise. !*/ bool operator!= ( const node_iterator& item ) const; /*! ensures - returns false if *this and item both reference the same node in the factor graph and true otherwise. !*/ node_iterator& operator++( ); /*! ensures - advances *this to the next node in the factor graph. - returns a reference to the updated *this (i.e. this is the ++object form of the increment operator) !*/ }; class neighbor_iterator { /*! WHAT THIS OBJECT REPRESENTS This is a simple forward iterator for iterating over the nodes/variables in this factor graph. This version of the iterator is used for iterating over the neighbors of another node in the graph. !*/ public: neighbor_iterator( ); /*! ensures - constructs an iterator in an undefined state !*/ neighbor_iterator( const neighbor_iterator& item ); /*! ensures - #*this is a copy of item !*/ neighbor_iterator& operator= ( const neighbor_iterator& item ); /*! ensures - #*this is a copy of item - returns #*this !*/ bool operator== ( const neighbor_iterator& item ) const; /*! ensures - returns true if *this and item both reference the same node in the factor graph and false otherwise. !*/ bool operator!= ( const neighbor_iterator& item ) const; /*! ensures - returns false if *this and item both reference the same node in the factor graph and true otherwise. !*/ neighbor_iterator& operator++( ); /*! ensures - advances *this to the next node in the factor graph. - returns a reference to the updated *this (i.e. this is the ++object form of the increment operator) !*/ }; unsigned long number_of_nodes ( ) const; /*! ensures - returns the number of nodes in the factor graph. Or in other words, returns the number of variables in the MAP problem. !*/ node_iterator begin( ) const; /*! ensures - returns an iterator to the first node in the graph. If no such node exists then returns end(). !*/ node_iterator end( ) const; /*! ensures - returns an iterator to one past the last node in the graph. !*/ neighbor_iterator begin( const node_iterator& it ) const; /*! requires - it == a valid iterator (i.e. it must be in the range [begin(), end())) ensures - returns an iterator to the first neighboring node of the node referenced by it. If no such node exists then returns end(it). !*/ neighbor_iterator begin( const neighbor_iterator& it ) const; /*! requires - it == a valid iterator. (i.e. it must be in the range [begin(i), end(i)) where i is some valid iterator. ) ensures - returns an iterator to the first neighboring node of the node referenced by it. If no such node exists then returns end(it). !*/ neighbor_iterator end( const node_iterator& it ) const; /*! requires - it == a valid iterator (i.e. it must be in the range [begin(), end())) ensures - returns an iterator to one past the last neighboring node of the node referenced by it. !*/ neighbor_iterator end( const neighbor_iterator& it ) const; /*! requires - it == a valid iterator. (i.e. it must be in the range [begin(i), end(i)) where i is some valid iterator. ) ensures - returns an iterator to one past the last neighboring node of the node referenced by it. !*/ unsigned long node_id ( const node_iterator& it ) const; /*! requires - it == a valid iterator (i.e. it must be in the range [begin(), end())) ensures - returns a number ID such that: - 0 <= ID < number_of_nodes() - ID == a number which uniquely identifies the node pointed to by it. !*/ unsigned long node_id ( const neighbor_iterator& it ) const; /*! requires - it == a valid iterator. (i.e. it must be in the range [begin(i), end(i)) where i is some valid iterator. ) ensures - returns a number ID such that: - 0 <= ID < number_of_nodes() - ID == a number which uniquely identifies the node pointed to by it. !*/ unsigned long num_states ( const node_iterator& it ) const; /*! requires - it == a valid iterator (i.e. it must be in the range [begin(), end())) ensures - returns the number of states attainable by the node/variable referenced by it. !*/ unsigned long num_states ( const neighbor_iterator& it ) const; /*! requires - it == a valid iterator. (i.e. it must be in the range [begin(i), end(i)) where i is some valid iterator. ) ensures - returns the number of states attainable by the node/variable referenced by it. !*/ // The next four functions all have the same contract. double factor_value (const node_iterator& it1, const node_iterator& it2, unsigned long s1, unsigned long s2) const; double factor_value (const neighbor_iterator& it1, const node_iterator& it2, unsigned long s1, unsigned long s2) const; double factor_value (const node_iterator& it1, const neighbor_iterator& it2, unsigned long s1, unsigned long s2) const; double factor_value (const neighbor_iterator& it1, const neighbor_iterator& it2, unsigned long s1, unsigned long s2) const; /*! requires - it1 == a valid iterator - it2 == a valid iterator - 0 <= s1 < num_states(it1) - 0 <= s2 < num_states(it2) - it1 and it2 reference nodes which are neighbors in the factor graph ensures - returns the value of the factor/potential function for the given pair of nodes, defined by it1 and it2, for the case where they take on the values s1 and s2 respectively. !*/ }; // ---------------------------------------------------------------------------------------- template < typename map_problem > void find_max_factor_graph_nmplp ( const map_problem& prob, std::vector<unsigned long>& map_assignment, unsigned long max_iter, double eps ); /*! requires - for all valid i: prob.num_states(i) >= 2 - map_problem == an object with an interface compatible with the map_problem object defined at the top of this file. - eps > 0 ensures - This function is a tool for approximately solving the given MAP problem in a graphical model or factor graph with pairwise potential functions. That is, it attempts to solve a certain kind of optimization problem which can be defined as follows: maximize: f(X) where X is a set of integer valued variables and f(X) can be written as the sum of functions which each involve only two variables from X. In reference to the prob object, the nodes in prob represent the variables in X and the functions which are summed are represented by prob.factor_value(). - #map_assignment == the result of the optimization. - #map_assignment.size() == prob.number_of_nodes() - for all valid i: - #map_assignment[prob.node_id(i)] < prob.num_states(i) - #map_assignment[prob.node_id(i)] == The approximate MAP assignment for node/variable i. - eps controls the stopping condition, smaller values of eps lead to more accurate solutions of the relaxed linear program but may take more iterations. Note that the algorithm will never execute more than max_iter iterations regardless of the setting of eps. - If the graph is tree-structured then this routine always gives the exact solution to the MAP problem. However, for graphs with cycles, the solution may be approximate. - This function is an implementation of the NMPLP algorithm introduced in the following papers: Fixing Max-Product: Convergent Message Passing Algorithms for MAP LP-Relaxations (2008) by Amir Globerson and Tommi Jaakkola Introduction to dual decomposition for inference (2011) by David Sontag, Amir Globerson, and Tommi Jaakkola !*/ // ---------------------------------------------------------------------------------------- } #endif // DLIB_FIND_MAX_FACTOR_GRAPH_nMPLP_ABSTRACT_Hh_