9db56ef08ea7c7c69304639485c7e1a79cb9fcef
[libdai.git] / include / dai / varset.h
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
3 * libDAI is licensed under the terms of the GNU General Public License version
4 * 2, or (at your option) any later version. libDAI is distributed without any
5 * warranty. See the file COPYING for more details.
6 *
7 * Copyright (C) 2002 Martijn Leisink [martijn@mbfys.kun.nl]
8 * Copyright (C) 2006-2009 Joris Mooij [joris dot mooij at libdai dot org]
9 * Copyright (C) 2002-2007 Radboud University Nijmegen, The Netherlands
10 */
11
12
13 /// \file
14 /// \brief Defines VarSet class
15
16
17 #ifndef __defined_libdai_varset_h
18 #define __defined_libdai_varset_h
19
20
21 #include <vector>
22 #include <map>
23 #include <cassert>
24 #include <ostream>
25 #include <dai/var.h>
26 #include <dai/util.h>
27 #include <dai/smallset.h>
28
29
30 namespace dai {
31
32
33 /// Represents a set of variables.
34 /** \note A VarSet is implemented using a SmallSet<Var> instead
35 * of the more natural std::set<Var> because of efficiency reasons.
36 * That is, internally, the variables in the set are sorted according
37 * to their labels: the set of variables \f$\{x_l\}_{l\in L}\f$ is
38 * represented as a vector \f$(x_{l(0)},x_{l(1)},\dots,x_{l(|L|-1)})\f$
39 * where \f$l(0) < l(1) < \dots < l(|L|-1)\f$
40 * and \f$L = \{l(0),l(1),\dots,l(|L|-1)\}\f$.
41 */
42 class VarSet : public SmallSet<Var> {
43 public:
44 /// Default constructor
45 VarSet() : SmallSet<Var>() {}
46
47 /// Construct from SmallSet<Var>
48 VarSet( const SmallSet<Var> &x ) : SmallSet<Var>(x) {}
49
50 /// Calculates the number of states of this VarSet.
51 /** The number of states of the Cartesian product of the variables in this VarSet
52 * is simply the product of the number of states of each variable in this VarSet.
53 * If *this corresponds with the set \f$\{x_l\}_{l\in L}\f$,
54 * where variable \f$x_l\f$ has label \f$l\f$, and denoting by \f$S_l\f$ the
55 * number of possible values ("states") of variable \f$x_l\f$, the number of
56 * joint configurations of the variables in \f$\{x_l\}_{l\in L}\f$ is given by \f$\prod_{l\in L} S_l\f$.
57 */
58 size_t nrStates() {
59 size_t states = 1;
60 for( VarSet::const_iterator n = begin(); n != end(); n++ )
61 states *= n->states();
62 return states;
63 }
64
65 /// Construct a VarSet with one element
66 VarSet( const Var &n ) : SmallSet<Var>(n) {}
67
68 /// Construct a VarSet with two elements
69 VarSet( const Var &n1, const Var &n2 ) : SmallSet<Var>(n1,n2) {}
70
71 /// Construct a VarSet from a range.
72 /** \tparam VarIterator Iterates over instances of type Var.
73 * \param begin Points to first Var to be added.
74 * \param end Points just beyond last Var to be added.
75 * \param sizeHint For efficiency, the number of elements can be speficied by sizeHint.
76 */
77 template <typename VarIterator>
78 VarSet( VarIterator begin, VarIterator end, size_t sizeHint=0 ) : SmallSet<Var>(begin,end,sizeHint) {}
79
80 /// Calculates the linear index in the Cartesian product of the variables in *this, which corresponds to a particular joint assignment of the variables specified by \a states.
81 /** \param states Specifies the states of some variables.
82 * \return The linear index in the Cartesian product of the variables in *this
83 * corresponding with the joint assignment specified by \a states, where it is
84 * assumed that \a states[\a m]==0 for all \a m in *this which are not in \a states.
85 *
86 * The linear index is calculated as follows. The variables in *this are
87 * ordered according to their label (in ascending order); say *this corresponds with
88 * the set \f$\{x_{l(0)},x_{l(1)},\dots,x_{l(n-1)}\}\f$ with \f$l(0) < l(1) < \dots < l(n-1)\f$,
89 * where variable \f$x_l\f$ has label \a l. Denote by \f$S_l\f$ the number of possible values
90 * ("states") of variable \f$x_l\f$. The argument \a states corresponds
91 * with a mapping \a s that assigns to each variable \f$x_l\f$ a state \f$s(x_l) \in \{0,1,\dots,S_l-1\}\f$,
92 * where \f$s(x_l)=0\f$ if \f$x_l\f$ is not specified in \a states. The linear index \a S corresponding
93 * with \a states is now calculated as:
94 * \f{eqnarray*}
95 * S &:=& \sum_{i=0}^{n-1} s(x_{l(i)}) \prod_{j=0}^{i-1} S_{l(j)} \\
96 * &= & s(x_{l(0)}) + s(x_{l(1)}) S_{l(0)} + s(x_{l(2)}) S_{l(0)} S_{l(1)} + \dots + s(x_{l(n-1)}) S_{l(0)} \cdots S_{l(n-2)}.
97 * \f}
98 *
99 * \note If *this corresponds with \f$\{x_l\}_{l\in L}\f$, and \a states specifies a state
100 * for each variable \f$x_l\f$ for \f$l\in L\f$, calcState(const std::map<Var,size_t> &) induces a mapping
101 * \f$\sigma : \prod_{l\in L} X_l \to \{0,1,\dots,\prod_{l\in L} S_l-1\}\f$ that
102 * maps a joint state to a linear index; this is the inverse of the mapping
103 * \f$\sigma^{-1}\f$ induced by calcStates(size_t).
104 */
105 size_t calcState( const std::map<Var, size_t> &states ) {
106 size_t prod = 1;
107 size_t state = 0;
108 for( VarSet::const_iterator n = begin(); n != end(); n++ ) {
109 std::map<Var, size_t>::const_iterator m = states.find( *n );
110 if( m != states.end() )
111 state += prod * m->second;
112 prod *= n->states();
113 }
114 return state;
115 }
116
117 /// Calculates the joint assignment of the variables in *this corresponding to the linear index \a linearState.
118 /** \param linearState should be smaller than nrStates().
119 * \return A mapping \f$s\f$ that maps each Var \f$x_l\f$ in *this to its state \f$s(x_l)\f$, as specified by \a linearState.
120 *
121 * The variables in *this are ordered according to their label (in ascending order); say *this corresponds with
122 * the set \f$\{x_{l(0)},x_{l(1)},\dots,x_{l(n-1)}\}\f$ with \f$l(0) < l(1) < \dots < l(n-1)\f$,
123 * where variable \f$x_l\f$ has label \a l. Denote by \f$S_l\f$ the number of possible values
124 * ("states") of variable \f$x_l\f$ with label \a l.
125 * The mapping \a s returned by this function is defined as:
126 * \f{eqnarray*}
127 * s(x_{l(i)}) = \left\lfloor\frac{S \mbox { mod } \prod_{j=0}^{i} S_{l(j)}}{\prod_{j=0}^{i-1} S_{l(j)}}\right\rfloor \qquad \mbox{for all $i=0,\dots,n-1$}.
128 * \f}
129 * where \f$S\f$ denotes the value of \a linearState.
130 *
131 * \note If *this corresponds with \f$\{x_l\}_{l\in L}\f$, calcStates(size_t) induces a mapping
132 * \f$\sigma^{-1} : \{0,1,\dots,\prod_{l\in L} S_l-1\} \to \prod_{l\in L} X_l\f$ that
133 * maps a linear index to a joint state; this is the inverse of the mapping \f$\sigma\f$
134 * induced by calcState(const std::map<Var,size_t> &).
135 */
136 std::map<Var, size_t> calcStates( size_t linearState ) {
137 std::map<Var, size_t> states;
138 for( VarSet::const_iterator n = begin(); n != end(); n++ ) {
139 states[*n] = linearState % n->states();
140 linearState /= n->states();
141 }
142 assert( linearState == 0 );
143 return states;
144 }
145
146 /// Writes a VarSet to an output stream
147 friend std::ostream& operator<< (std::ostream &os, const VarSet& ns) {
148 os << "{";
149 for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ )
150 os << (n != ns.begin() ? "," : "") << *n;
151 os << "}";
152 return( os );
153 }
154 };
155
156
157 } // end of namespace dai
158
159
160 /** \example example_varset.cpp
161 * This example shows how to use the Var and VarSet classes. It also explains the concept of "states" for VarSets.
162 *
163 * \section Output
164 * \verbinclude examples/example_varset.out
165 *
166 * \section Source
167 */
168
169
170 #endif