summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/optimization/find_max_factor_graph_nmplp_abstract.h
blob: 3dd9aead0bd2bae4fb24b05266a045d976f7a264 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
// 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_