IMP  2.3.0
The Integrative Modeling Platform
assignment_containers.h
Go to the documentation of this file.
1 /**
2  * \file IMP/domino/assignment_containers.h
3  * \brief A Bayesian inference-based sampler.
4  *
5  * Copyright 2007-2014 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPDOMINO_ASSIGNMENT_CONTAINERS_H
10 #define IMPDOMINO_ASSIGNMENT_CONTAINERS_H
11 
12 #include <IMP/domino/domino_config.h>
13 #include "Assignment.h"
14 #include "Order.h"
15 #include "subset_scores.h"
16 #include <IMP/base/Vector.h>
17 #include <IMP/base/hash.h>
18 #include <boost/unordered_map.hpp>
20 
21 #include <algorithm>
22 #include <boost/random/uniform_int.hpp>
23 #include <boost/random/uniform_real.hpp>
24 #include <boost/shared_array.hpp>
25 #include <cstdio>
26 #include <queue>
27 
28 #if IMP_DOMINO_HAS_RMF
29 #include <RMF/HDF5/Group.h>
30 #include <RMF/HDF5/File.h>
31 #endif
32 
33 #ifdef _MSC_VER
34 #include <io.h>
35 #endif
36 
37 IMPDOMINO_BEGIN_NAMESPACE
38 
39 /** The base class for containers of assignments. Assignments are stored
40  in these rather than as Assignments to help increase efficiency as
41  well as provide flexibility as to how and where they are stored.
42 */
43 class IMPDOMINOEXPORT AssignmentContainer : public IMP::base::Object {
44  public:
45  AssignmentContainer(std::string name = "AssignmentContainer %1%");
46  virtual unsigned int get_number_of_assignments() const = 0;
47  virtual Assignment get_assignment(unsigned int i) const = 0;
48  virtual Assignments get_assignments(IntRange ir) const = 0;
49  virtual Assignments get_assignments() const = 0;
50  virtual void add_assignment(const Assignment &a) = 0;
51  virtual void add_assignments(const Assignments &as) = 0;
52  //! Get all the assignments for the ith particle
53  virtual Ints get_particle_assignments(unsigned int i) const = 0;
54 
55  virtual ~AssignmentContainer();
56 };
57 
59 
60 /** Store a set of assignments in a somewhat more compact form in memory
61  than the ListAssignmentContainer.
62  */
63 class IMPDOMINOEXPORT PackedAssignmentContainer : public AssignmentContainer {
64  // store all as one vector
65  Ints d_;
66  int width_;
67 
68  public:
69  PackedAssignmentContainer(std::string name =
70  "PackedAssignmentContainer %1%");
71  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
72  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
73  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
76 };
77 
78 #ifndef IMP_DOXYGEN
79 
80 inline unsigned int PackedAssignmentContainer::get_number_of_assignments()
81  const {
82  if (width_ == -1) return 0;
83  return d_.size() / width_;
84 }
85 
86 inline Assignment PackedAssignmentContainer::get_assignment(unsigned int i)
87  const {
88  IMP_USAGE_CHECK(i < get_number_of_assignments(),
89  "Invalid assignment requested: " << i);
90  IMP_USAGE_CHECK(width_ > 0, "Uninitialized PackedAssignmentContainer.");
91  return Assignment(d_.begin() + i * width_, d_.begin() + (i + 1) * width_);
92 }
93 
94 inline void PackedAssignmentContainer::add_assignment(const Assignment &a) {
96  if (width_ == -1) {
97  width_ = a.size();
98  }
99  IMP_USAGE_CHECK(static_cast<int>(a.size()) == width_,
100  "Sizes don't match " << width_ << " vs " << a.size());
102  for (unsigned int i = 0; i < get_number_of_assignments(); ++i) {
103  IMP_INTERNAL_CHECK(get_assignment(i) != a, "Assignment "
104  << a << " already here.");
105  }
106  }
107  d_.insert(d_.end(), a.begin(), a.end());
108 }
109 #endif
110 
111 /** Simple storage of a set of Assignments. Prefer PackedAssignmentContainer,
112  I think.
113  */
114 class IMPDOMINOEXPORT ListAssignmentContainer : public AssignmentContainer {
115  // store all as one vector
116  Assignments d_;
117 
118  public:
119  ListAssignmentContainer(std::string name = "ListAssignmentContainer %1%");
120  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
121  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
122  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
125 };
126 
127 #ifndef IMP_DOXYGEN
128 inline unsigned int ListAssignmentContainer::get_number_of_assignments() const {
129  return d_.size();
130 }
131 
132 inline Assignment ListAssignmentContainer::get_assignment(unsigned int i)
133  const {
134  return d_[i];
135 }
136 
137 inline void ListAssignmentContainer::add_assignment(const Assignment &a) {
138  d_.push_back(a);
139 }
140 #endif
141 
142 /** Store a list of k assignments chosen from all of the ones added to this
143  table. The states are chosen uniformly.
144 
145  This doesn't seem very useful
146  */
147 class IMPDOMINOEXPORT SampleAssignmentContainer : public AssignmentContainer {
148  // store all as one vector
149  Ints d_;
150  int width_;
151  unsigned int k_;
152  unsigned int i_;
153  boost::uniform_real<double> select_;
154  boost::uniform_int<> place_;
155 
156  public:
157  SampleAssignmentContainer(unsigned int k,
158  std::string name =
159  "SampleAssignmentContainer %1%");
160  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
161  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
162  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
165 };
166 
167 #ifndef IMP_DOXYGEN
168 inline unsigned int SampleAssignmentContainer::get_number_of_assignments()
169  const {
170  return d_.size() / width_;
171 }
172 
173 inline Assignment SampleAssignmentContainer::get_assignment(unsigned int i)
174  const {
175  return Assignment(d_.begin() + i * width_, d_.begin() + (i + 1) * width_);
176 }
177 #endif
178 
179 #if IMP_DOMINO_HAS_RMF || defined(IMP_DOXYGEN)
180 /** Store the assignments in an HDF5DataSet. Make sure to delete this
181  container before trying to read from the same data set (unless
182  you pass the data set explicitly, in which case it may be OK).
183 
184  The format on disk should
185  not, yet, be considered stable.
186  */
187 class IMPDOMINOEXPORT WriteHDF5AssignmentContainer
188  : public AssignmentContainer {
189  RMF::HDF5::IndexDataSet2D ds_;
190  Order order_;
191  Ints cache_;
192  unsigned int max_cache_;
193  void flush();
194  virtual void do_destroy() IMP_OVERRIDE { flush(); }
195 
196  public:
197  WriteHDF5AssignmentContainer(RMF::HDF5::Group parent, const Subset &s,
198  const kernel::ParticlesTemp &all_particles,
199  std::string name);
200 
201  WriteHDF5AssignmentContainer(RMF::HDF5::IndexDataSet2D dataset,
202  const Subset &s,
203  const kernel::ParticlesTemp &all_particles,
204  std::string name);
205  void set_cache_size(unsigned int words);
206  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
207  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
208  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
211 };
212 
213 /** Store the assignments in an HDF5DataSet. The format on disk should not,
214  yet, be considered stable.
215  */
216 class IMPDOMINOEXPORT ReadHDF5AssignmentContainer : public AssignmentContainer {
217  RMF::HDF5::IndexConstDataSet2D ds_;
218  Order order_;
219  Ints cache_;
220  unsigned int max_cache_;
221  void flush();
222 
223  public:
224  ReadHDF5AssignmentContainer(RMF::HDF5::IndexConstDataSet2D dataset,
225  const Subset &s,
226  const kernel::ParticlesTemp &all_particles,
227  std::string name);
228  void set_cache_size(unsigned int words);
229  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
230  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
231  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
234 };
235 #endif
236 
237 /** Store the assignments on disk as binary data. Use a ReadAssignmentContainer
238  to read them back. The resulting file is not guaranteed to work on any
239  platform other than the one it was created on and the format may change.
240  */
241 class IMPDOMINOEXPORT WriteAssignmentContainer : public AssignmentContainer {
242  int f_;
243  Order order_;
244  Ints cache_;
245  unsigned int max_cache_;
246  int number_;
247  void flush();
248 
249  virtual void do_destroy() IMP_OVERRIDE {
250  flush();
251 #ifdef _MSC_VER
252  _close(f_);
253 #else
254  close(f_);
255 #endif
256  }
257 
258  public:
259  WriteAssignmentContainer(std::string out_file, const Subset &s,
260  const kernel::ParticlesTemp &all_particles,
261  std::string name);
262  void set_cache_size(unsigned int words);
263  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
264  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
265  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
268 };
269 
270 /** Read the assignments from binary data on disk. Use a
271  WriteAssignmentContainer to write them. Make sure to destroy the
272  WriteAssignmentContainer before trying to read from the file.
273  */
274 class IMPDOMINOEXPORT ReadAssignmentContainer : public AssignmentContainer {
275  int f_;
276  Order order_;
277  mutable Ints cache_;
278  unsigned int max_cache_;
279  mutable int offset_;
280  int size_;
281  virtual void do_destroy() IMP_OVERRIDE {
282 #ifdef _MSC_VER
283  _close(f_);
284 #else
285  close(f_);
286 #endif
287  }
288 
289  public:
290  ReadAssignmentContainer(std::string out_file, const Subset &s,
291  const kernel::ParticlesTemp &all_particles,
292  std::string name);
293  void set_cache_size(unsigned int words);
294  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
295  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
296  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
299 };
300 
301 /** Expose a range [begin, end) of an inner assignment container to
302  consumers. One cannot add assignments to this container.
303  */
304 class IMPDOMINOEXPORT RangeViewAssignmentContainer
305  : public AssignmentContainer {
307  int begin_, end_;
308 
309  public:
310  RangeViewAssignmentContainer(AssignmentContainer *inner, unsigned int begin,
311  unsigned int end);
312  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
313  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
314  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
317 };
318 
319 /** Store a set of k top scoring assignments
320  */
321 class IMPDOMINOEXPORT HeapAssignmentContainer : public AssignmentContainer {
322  typedef std::pair<Assignment, double> AP;
323  struct GreaterSecond {
324  bool operator()(const AP &a, const AP &b) { return a.second < b.second; }
325  };
326  typedef base::Vector<AP> C;
327  C d_;
328  Subset subset_;
329  Slices slices_;
330  kernel::Restraints rs_;
331  unsigned int k_; // max number of assignments (heap size)
332  base::Pointer<RestraintCache> rssf_; // to score candidate assignments
333  public:
334  HeapAssignmentContainer(Subset subset, unsigned int k, RestraintCache *rssf,
335  std::string name = "HeapAssignmentContainer %1%");
336  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
337  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
338  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
341 };
342 
343 /** This is a wrapper for an AssignmentContainer that throws a ValueException
344  if more than a certain number of states are added.*/
345 class IMPDOMINOEXPORT CappedAssignmentContainer : public AssignmentContainer {
346  typedef AssignmentContainer P;
348  unsigned int max_;
349  void check_number() const;
350 
351  public:
352  CappedAssignmentContainer(AssignmentContainer *contained, int max_states,
353  std::string name);
354  virtual unsigned int get_number_of_assignments() const IMP_OVERRIDE;
355  virtual Assignment get_assignment(unsigned int i) const IMP_OVERRIDE;
356  virtual void add_assignment(const Assignment &a) IMP_OVERRIDE;
359 };
360 
361 IMPDOMINO_END_NAMESPACE
362 
363 #endif /* IMPDOMINO_ASSIGNMENT_CONTAINERS_H */
#define IMP_IF_CHECK(level)
Execute the code block if a certain level checks are on.
Definition: check_macros.h:106
A Bayesian inference-based sampler.
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Definition: object_macros.h:25
Store a persistent ordering for a subset based on the list.
Definition: Order.h:29
#define IMP_OBJECT_LOG
Set the log level to the object's log level.
Definition: log_macros.h:297
IO support.
A smart pointer to a reference counted object.
Definition: Pointer.h:87
Represent a subset of the particles being optimized.
Definition: Subset.h:33
Cluster sets of points.
#define IMP_INTERNAL_CHECK(expr, message)
An assertion to check for internal errors in IMP. An IMP::ErrorException will be thrown.
Definition: check_macros.h:141
#define IMP_ASSIGNMENT_CONTAINER_METHODS(Name)
Definition: domino_macros.h:82
A Bayesian inference-based sampler.
A class for storing lists of IMP items.
Common base class for heavy weight IMP objects.
Definition: Object.h:106
#define IMP_OBJECTS(Name, PluralName)
Define the types for storing sets of objects.
Definition: object_macros.h:52
Store a configuration of a subset.
Definition: Assignment.h:32
virtual void do_destroy()
Definition: Object.h:231
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:170
A Bayesian inference-based sampler.
#define IMP_OVERRIDE
Cause a compile error if this method does not override a parent method.