PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/toolkits/graphical_models/deprecated/factors/discrete_assignment.hpp

https://github.com/michaelkook/GraphLab-2
C++ Header | 371 lines | 204 code | 61 blank | 106 comment | 26 complexity | 3d9f25d5135ea865b563a9f125349285 MD5 | raw file
Possible License(s): ISC, Apache-2.0
  1. /**
  2. * Copyright (c) 2009 Carnegie Mellon University.
  3. * All rights reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing,
  12. * software distributed under the License is distributed on an "AS
  13. * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  14. * express or implied. See the License for the specific language
  15. * governing permissions and limitations under the License.
  16. *
  17. * For more about this software visit:
  18. *
  19. * http://www.graphlab.ml.cmu.edu
  20. *
  21. */
  22. #ifndef DISCRETE_ASSIGNMENT_HPP
  23. #define DISCRETE_ASSIGNMENT_HPP
  24. #include "discrete_variable.hpp"
  25. #include "discrete_domain.hpp"
  26. #include <graphlab/macros_def.hpp>
  27. template<size_t MAX_DIM>
  28. class discrete_assignment {
  29. public:
  30. typedef discrete_domain<MAX_DIM> domain_type;
  31. typedef discrete_variable variable_type;
  32. //! Construct an empty discrete_assignment
  33. discrete_assignment() : _index(0) { }
  34. //! Construct a zero discrete_assignment over the domain
  35. discrete_assignment(const domain_type& args) :
  36. _args(args), _index(0) {
  37. for(size_t i = 0; i < args.num_vars(); ++i)
  38. _asgs[i] = 0;
  39. }
  40. //! Construct a zero discrete_assignment over the domain
  41. discrete_assignment(const domain_type& args, size_t index) :
  42. _args(args), _index(index) {
  43. assert(index < _args.size());
  44. recompute_asgs();
  45. }
  46. //! construct an discrete_assignment from two variables
  47. discrete_assignment(const variable_type& v1, size_t asg1) :
  48. _args(v1), _index(asg1) {
  49. assert(asg1 < v1.size());
  50. _asgs[0] = asg1;
  51. }
  52. //! construct an discrete_assignment from two variables
  53. discrete_assignment(const variable_type& v1, size_t asg1,
  54. const variable_type& v2, size_t asg2) :
  55. _args(v1, v2), _index(0) {
  56. set_asg(v1.id(), asg1);
  57. set_asg(v2.id(), asg2);
  58. }
  59. //! Construct an discrete_assignment from a vector of variables and a
  60. //! vector of values
  61. discrete_assignment(const domain_type& args,
  62. const std::vector<size_t>& values) :
  63. _args(args), _index(0) {
  64. for(size_t i = 0; i < _args.num_vars(); ++i) {
  65. assert(values[i] < args.var(i).size());
  66. _asgs[i] = values[i];
  67. }
  68. recompute_linear_index();
  69. }
  70. // //! Construct the union of two discrete_assignments
  71. // inline discrete_assignment& operator&=(const discrete_assignment& asg2) {
  72. // discrete_assignment asg1 = *this;
  73. // const domain_type& dom1 = asg1.args();
  74. // const domain_type& dom2 = asg2.args();
  75. // _args = dom1 + dom2;
  76. // _index = 0;
  77. // size_t i = 0, j1 = 0, j2 = 0;
  78. // for( ; i < _args.num_vars() &&
  79. // (j1 < dom1.num_vars() || j2 < dom2.num_vars());
  80. // ++i) {
  81. // // If the the two discrete_assignments share a same variable
  82. // if(j1 < dom1.num_vars() &&
  83. // _args.var(i) == dom1.var(j1) &&
  84. // j2 < dom2.num_vars() &&
  85. // _args.var(i) == dom2.var(j2)) {
  86. // // Then they must have the same discrete_assignment
  87. // // assert(asg1._asgs[j1] == asg2._asgs[j2]);
  88. // _asgs[i] = asg1._asgs[j1];
  89. // ++j1; ++j2;
  90. // } else if(j1 < dom1.num_vars() &&
  91. // _args.var(i) == dom1.var(j1) ) {
  92. // _asgs[i] = asg1._asgs[j1];
  93. // ++j1;
  94. // } else if(j2 < dom2.num_vars() &&
  95. // _args.var(i) == dom2.var(j2) ) {
  96. // _asgs[i] = asg2._asgs[j2];
  97. // ++j2;
  98. // } else {
  99. // // Unreachable state
  100. // assert(false);
  101. // }
  102. // }
  103. // assert(i == _args.num_vars());
  104. // assert(j1 == dom1.num_vars());
  105. // assert(j2 == dom2.num_vars());
  106. // recompute_linear_index();
  107. // return *this;
  108. // }
  109. // // Construct the union of two discrete_assignments
  110. // discrete_assignment operator&(const discrete_assignment& other) const {
  111. // discrete_assignment new_asg = *this;
  112. // return new_asg &= other;
  113. // }
  114. //! Construct the union of two discrete_assignments
  115. inline discrete_assignment operator&(const discrete_assignment& other) const {
  116. discrete_assignment result(args() + other.args());
  117. // Require disjoint discrete_assignments
  118. // assert(args().size() + other.args().size() == result.size());
  119. size_t i = 0, j = 0, k = 0;
  120. while(i < num_vars() && j < other.num_vars()) {
  121. // extra increment if necessary
  122. assert(k < result.num_vars());
  123. result._asgs[k] =
  124. (result.args().var(k) == args().var(i))?
  125. asg_at(i) : other.asg_at(j);
  126. // if the variables are the same then the discrete_assignments must
  127. // also be the same
  128. assert(!(args().var(i) == other.args().var(j)) ||
  129. (asg_at(i) == other.asg_at(j)));
  130. // move indexs
  131. i += (args().var(i) == result.args().var(k));
  132. j += (other.args().var(j) == result.args().var(k));
  133. k++;
  134. }
  135. while(i < num_vars())
  136. result._asgs[k++] = asg_at(i++);
  137. while(j < other.num_vars())
  138. result._asgs[k++] = other.asg_at(j++);
  139. // recompute the linear index of the result
  140. result.recompute_linear_index();
  141. return result;
  142. }
  143. // Construct the union of two discrete_assignments
  144. inline discrete_assignment& operator&=(const discrete_assignment& other) {
  145. discrete_assignment tmp = *this & other;
  146. *this = tmp;
  147. return *this;
  148. }
  149. //! Get the variable in the discrete_assignment
  150. const domain_type& args() const { return _args; }
  151. //! get the number of variables
  152. size_t num_vars() const { return _args.num_vars(); }
  153. //! get the size of the discrete_assignment
  154. size_t size() const { return _args.size(); }
  155. //! Get the next discrete_assignment
  156. discrete_assignment& operator++() {
  157. assert(_index < _args.size());
  158. // Increment the index
  159. ++_index;
  160. // Update the discrete_assignments
  161. for(size_t i = 0; i < _args.num_vars(); ++i) {
  162. _asgs[i]= ((_asgs[i] + 1) % _args.var(i).size());
  163. if(_asgs[i] > 0) { return *this; }
  164. }
  165. // Reached end
  166. make_end();
  167. return *this;
  168. }
  169. //! Uniformly sample a new index value
  170. void uniform_sample() {
  171. set_index( graphlab::random::fast_uniform(size_t(0), size() - 1) );
  172. }
  173. //! Get the index of this discrete_assignment
  174. size_t linear_index() const { return _index; }
  175. size_t asg(size_t var_id) const {
  176. size_t index = _args.var_location(var_id);
  177. assert(index < _args.num_vars());
  178. return _asgs[index];
  179. }
  180. size_t asg_at(size_t index) const {
  181. assert(index < _args.num_vars());
  182. return _asgs[index];
  183. }
  184. void set_asg(size_t var_id, size_t value) {
  185. size_t index = _args.var_location(var_id);
  186. assert(index < _args.num_vars());
  187. assert(value < _args.var(index).size());
  188. _asgs[index] = value;
  189. recompute_linear_index();
  190. }
  191. void set_asg_at(size_t index, size_t value) {
  192. assert(index < _args.num_vars());
  193. assert(value < _args.var(index).size());
  194. _asgs[index] = value;
  195. recompute_linear_index();
  196. }
  197. void set_index(size_t index) {
  198. assert(index < _args.size());
  199. _index = index;
  200. recompute_asgs();
  201. }
  202. //! Tests whether two discrete_assignments are equal
  203. bool operator==(const discrete_assignment& other) const {
  204. return _index == other._index;
  205. }
  206. //! Tests whether two discrete_assignments are not equal
  207. bool operator!=(const discrete_assignment& other) const {
  208. return _index != other._index;
  209. }
  210. //! Tests whether this discrete_assignment is < other
  211. bool operator<(const discrete_assignment& other) const {
  212. return _index < other._index;
  213. }
  214. //! Make this an ending discrete_assignment
  215. void make_end() {
  216. _index = -1;
  217. // for(size_t i = 0; i < _args.num_vars(); ++i)
  218. // _asgs[i] = _args.var(i).size();
  219. }
  220. //! Restrict the discrete_assignment to an discrete_assignment over the subdomain
  221. discrete_assignment restrict(const domain_type& sub_domain) const {
  222. discrete_assignment other_asg(sub_domain);
  223. size_t index = 0;
  224. // Map the variables
  225. for(size_t i = 0; i < _args.num_vars() &&
  226. index < sub_domain.num_vars(); ++i) {
  227. if(sub_domain.var(index) == _args.var(i)) {
  228. other_asg._asgs[index] = _asgs[i];
  229. index++;
  230. }
  231. }
  232. assert(index == sub_domain.num_vars());
  233. // Recompute the index
  234. other_asg.recompute_linear_index();
  235. return other_asg;
  236. } // end of restrict
  237. //! Update the variables in this discrete_assignment with the values in the
  238. //! other discrete_assignment
  239. void update(const discrete_assignment& other) {
  240. for(size_t i = 0, j = 0;
  241. i < num_vars() && j < other.num_vars(); ) {
  242. if(_args.var(i) == other._args.var(j)) {
  243. _asgs[i] = other._asgs[j]; i++; j++;
  244. }
  245. while(i < num_vars() &&
  246. _args.var(i) < other.args().var(j)) i++;
  247. while(j < other.num_vars() &&
  248. other.args().var(j) < _args.var(i)) j++;
  249. }
  250. recompute_linear_index();
  251. }
  252. void load(graphlab::iarchive& arc) {
  253. arc >> _args;
  254. arc >> _index;
  255. recompute_asgs();
  256. }
  257. void save(graphlab::oarchive& arc) const {
  258. arc << _args;
  259. arc << _index;
  260. }
  261. private:
  262. //! Recompute the index from the discrete_assignment
  263. void recompute_linear_index() {
  264. size_t multiple = 1;
  265. // Clear the index
  266. _index = 0;
  267. for(size_t i = 0; i < _args.num_vars(); ++i) {
  268. _index += multiple * _asgs[i];
  269. // assert(_args.var(i).nasgs > 0);
  270. multiple *= _args.var(i).size();
  271. }
  272. }
  273. //! Recompute the discrete_assignments from the index
  274. void recompute_asgs() {
  275. assert(_index < _args.size());
  276. size_t quotient = _index;
  277. for(size_t i = 0; i < _args.num_vars(); ++i) {
  278. _asgs[i] = quotient % _args.var(i).size();
  279. quotient /= _args.var(i).size();
  280. // assert(_asgs[i] < _args.var(i).size());
  281. }
  282. }
  283. domain_type _args;
  284. uint16_t _asgs[MAX_DIM];
  285. uint32_t _index;
  286. };
  287. template<size_t MAX_DIM>
  288. discrete_assignment<MAX_DIM> discrete_domain<MAX_DIM>::begin() const {
  289. return discrete_assignment<MAX_DIM>(*this);
  290. }
  291. template<size_t MAX_DIM>
  292. discrete_assignment<MAX_DIM> discrete_domain<MAX_DIM>::end() const {
  293. discrete_assignment<MAX_DIM> ret(*this);
  294. ret.make_end();
  295. return ret;
  296. }
  297. template<size_t MAX_DIM>
  298. std::ostream& operator<<(std::ostream& out,
  299. const discrete_assignment<MAX_DIM>& asg) {
  300. out << "{";
  301. for(size_t i = 0; i < asg.args().num_vars(); ++i) {
  302. out << "v_" << asg.args().var(i).id()
  303. << "=" << asg.asg_at(i);
  304. if(i < asg.args().num_vars() - 1) out << ", ";
  305. }
  306. out << "}=" << asg.linear_index();
  307. return out;
  308. }
  309. #include <graphlab/macros_undef.hpp>
  310. #endif