83d35af5b254935401191e249fe7cd2db7347965
1 /* Copyright (C) 2006-2008 Joris Mooij [j dot mooij at science dot ru dot nl]
2 Copyright (C) 2002 Martijn Leisink [martijn@mbfys.kun.nl]
3 Radboud University Nijmegen, The Netherlands
5 This file is part of libDAI.
7 libDAI is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 libDAI is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with libDAI; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #ifndef __defined_libdai_index_h
24 #define __defined_libdai_index_h
31 #include <dai/varset.h>
37 /// Tool for looping over the states of several variables.
38 /** The class IndexFor is an important tool for indexing of Factors.
39 * Its usage can best be explained by an example.
40 * Assume indexVars, forVars are two VarSets.
41 * Then the following code:
43 * IndexFor i( indexVars, forVars );
44 * for( ; i >= 0; ++i ) {
48 * loops over all joint states of the variables in forVars,
49 * and (long)i is equal to the linear index of the corresponding
50 * state of indexVars, where the variables in indexVars that are
51 * not in forVars assume their zero'th value.
55 /// The current linear index corresponding to the state of indexVars
58 /// For each variable in forVars, the amount of change in _index
59 std::vector
<long> _sum
;
61 /// For each variable in forVars, the current state
62 std::vector
<size_t> _count
;
64 /// For each variable in forVars, its number of possible values
65 std::vector
<size_t> _dims
;
68 /// Default constructor
74 IndexFor( const VarSet
& indexVars
, const VarSet
& forVars
) : _count( forVars
.size(), 0 ) {
77 _dims
.reserve( forVars
.size() );
78 _sum
.reserve( forVars
.size() );
80 VarSet::const_iterator j
= forVars
.begin();
81 for( VarSet::const_iterator i
= indexVars
.begin(); i
!= indexVars
.end(); ++i
) {
82 for( ; j
!= forVars
.end() && *j
<= *i
; ++j
) {
83 _dims
.push_back( j
->states() );
84 _sum
.push_back( (*i
== *j
) ? sum
: 0 );
88 for( ; j
!= forVars
.end(); ++j
) {
89 _dims
.push_back( j
->states() );
96 IndexFor( const IndexFor
& ind
) : _index(ind
._index
), _sum(ind
._sum
), _count(ind
._count
), _dims(ind
._dims
) {}
98 /// Assignment operator
99 IndexFor
& operator=( const IndexFor
&ind
) {
109 /// Sets the index back to zero
111 fill( _count
.begin(), _count
.end(), 0 );
116 /// Conversion to long
117 operator long () const {
121 /// Pre-increment operator
122 IndexFor
& operator++ () {
126 while( i
< _count
.size() ) {
128 if( ++_count
[i
] < _dims
[i
] )
130 _index
-= _sum
[i
] * _dims
[i
];
135 if( i
== _count
.size() )
143 /// MultiFor makes it easy to perform a dynamic number of nested for loops.
144 /** An example of the usage is as follows:
146 * std::vector<size_t> dims;
147 * dims.push_back( 3 );
148 * dims.push_back( 4 );
149 * dims.push_back( 5 );
150 * for( MultiFor s(dims); s.valid(); ++s )
151 * cout << "linear index: " << (size_t)s << " corresponds with indices " << s[0] << ", " << s[1] << ", " << s[2] << endl;
153 * which would be equivalent to:
156 * for( size_t s0 = 0; s0 < 3; s0++ )
157 * for( size_t s1 = 0; s1 < 4; s1++ )
158 * for( size_t s2 = 0; s2 < 5; s++, s2++ )
159 * cout << "linear index: " << (size_t)s << " corresponds with indices " << s0 << ", " << s1 << ", " << s2 << endl;
164 std::vector
<size_t> _dims
;
165 std::vector
<size_t> _states
;
169 /// Default constructor
170 MultiFor() : _dims(), _states(), _state(0) {}
172 /// Initialize from vector of index dimensions
173 MultiFor( const std::vector
<size_t> &d
) : _dims(d
), _states(d
.size(),0), _state(0) {}
176 MultiFor( const MultiFor
&x
) : _dims(x
._dims
), _states(x
._states
), _state(x
._state
) {}
178 /// Assignment operator
179 MultiFor
& operator=( const MultiFor
& x
) {
188 /// Return linear state
189 operator size_t() const {
194 /// Return k'th index
195 size_t operator[]( size_t k
) const {
197 assert( k
< _states
.size() );
201 /// Prefix increment operator
202 MultiFor
& operator++() {
206 for( i
= 0; i
!= _states
.size(); i
++ ) {
207 if( ++(_states
[i
]) < _dims
[i
] )
211 if( i
== _states
.size() )
217 /// Postfix increment operator
218 void operator++( int ) {
222 /// Returns true if the current state is valid
224 return( _state
>= 0 );
229 /// Tool for calculating permutations of multiple indices.
232 std::vector
<size_t> _dims
;
233 std::vector
<size_t> _sigma
;
236 /// Default constructor
237 Permute() : _dims(), _sigma() {}
239 /// Initialize from vector of index dimensions and permutation sigma
240 Permute( const std::vector
<size_t> &d
, const std::vector
<size_t> &sigma
) : _dims(d
), _sigma(sigma
) {
241 assert( _dims
.size() == _sigma
.size() );
245 Permute( const Permute
&x
) : _dims(x
._dims
), _sigma(x
._sigma
) {}
247 /// Assignment operator
248 Permute
& operator=( const Permute
&x
) {
256 /// Converts the linear index li to a vector index
257 /// corresponding with the dimensions in _dims,
258 /// permutes it according to sigma,
259 /// and converts it back to a linear index
260 /// according to the permuted dimensions.
261 size_t convert_linear_index( size_t li
) {
262 size_t N
= _dims
.size();
264 // calculate vector index corresponding to linear index
265 std::vector
<size_t> vi
;
268 for( size_t k
= 0; k
< N
; k
++ ) {
269 vi
.push_back( li
% _dims
[k
] );
274 // convert permuted vector index to corresponding linear index
277 for( size_t k
= 0; k
< N
; k
++ ) {
278 sigma_li
+= vi
[_sigma
[k
]] * prod
;
279 prod
*= _dims
[_sigma
[k
]];
287 /// Contains the state of variables within a VarSet and useful things to do with this information.
288 /// This is very similar to a MultiFor, but tailored for Vars and Varsets.
291 typedef std::map
<Var
, size_t> states_type
;
297 /// Default constructor
298 State() : state(0), states() {}
300 /// Initialize from VarSet
301 State( const VarSet
&vs
) : state(0) {
302 for( VarSet::const_iterator v
= vs
.begin(); v
!= vs
.end(); v
++ )
307 State( const State
& x
) : state(x
.state
), states(x
.states
) {}
309 /// Assignment operator
310 State
& operator=( const State
&x
) {
318 /// Return linear state
319 operator size_t() const {
324 /// Return state of variable n,
325 /// or zero if n is not in this State
326 size_t operator() ( const Var
&n
) const {
328 states_type::const_iterator entry
= states
.find( n
);
329 if( entry
== states
.end() )
332 return entry
->second
;
335 /// Return linear state of variables in varset,
336 /// setting them to zero if they are not in this State
337 size_t operator() ( const VarSet
&vs
) const {
341 for( VarSet::const_iterator v
= vs
.begin(); v
!= vs
.end(); v
++ ) {
342 states_type::const_iterator entry
= states
.find( *v
);
343 if( entry
!= states
.end() )
344 vs_state
+= entry
->second
* prod
;
350 /// Postfix increment operator
351 void operator++( int ) {
354 states_type::iterator entry
= states
.begin();
355 while( entry
!= states
.end() ) {
356 if( ++(entry
->second
) < entry
->first
.states() )
361 if( entry
== states
.end() )
366 /// Returns true if the current state is valid
368 return( state
>= 0 );
373 } // end of namespace dai