OpenGM  2.3.x
Discrete Graphical Model Library
lunary.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_LEARNABLE_UNARY_FUNCTION_HXX
3 #define OPENGM_LEARNABLE_UNARY_FUNCTION_HXX
4 
5 #include <algorithm>
6 #include <vector>
7 #include <cmath>
8 
9 #include "opengm/opengm.hxx"
13 
14 namespace opengm {
15 namespace functions {
16 namespace learnable {
17 
18 
19 
20 
21 
22 template<class V, class I>
24  std::vector<V> features;
25  std::vector<I> weightIds;
26 };
27 
28 
29 
30 
31 template<class T, class I , class L>
32 class LUnary
33  : public opengm::FunctionBase<opengm::functions::learnable::LUnary<T, I, L>, T, I, L>
34 {
35 public:
36  typedef T ValueType;
37  typedef T V;
38  typedef L LabelType;
39  typedef I IndexType;
40 
42  :
43  weights_(NULL),
44  numberOfLabels_(0),
45  offsets_(),
46  weightIds_(),
47  features_()
48  {
49 
50  }
51 
52  LUnary(
53  const opengm::learning::Weights<T>& weights,
54  std::vector<FeaturesAndIndices<T, I> > featuresAndIndicesPerLabel
55  );
56 
57  LUnary(
58  const opengm::learning::Weights<T>& weights,
59  const LabelType numberOfLabels,
62  const bool makeFirstEntryConst
63  );
64 
65 
66  L shape(const size_t) const;
67  size_t size() const;
68  size_t dimension() const;
69  template<class ITERATOR> T operator()(ITERATOR) const;
70 
71  // parameters
72  void setWeights(const opengm::learning::Weights<T>& weights) const{
73  weights_ = &weights;
74  }
75 
76  size_t numberOfWeights()const{
77  return weightIds_.size();
78  }
79 
80  I weightIndex(const size_t weightNumber) const{
81  return weightIds_[weightNumber];
82  }
83 
84  template<class ITERATOR>
85  T weightGradient(size_t,ITERATOR) const;
86 
87 private:
88 
89 
90 protected:
91 
92  size_t numWeightsForL(const LabelType l )const{
93  return offsets_[0*numberOfLabels_ + l];
94  }
95  size_t weightIdOffset(const LabelType l )const{
96  return offsets_[1*numberOfLabels_ + l];
97  }
98  size_t featureOffset(const LabelType l )const{
99  return offsets_[2*numberOfLabels_ + l];
100  }
101 
103 
104  IndexType numberOfLabels_;
105  std::vector<IndexType> offsets_;
106  std::vector<size_t> weightIds_;
107  std::vector<ValueType> features_;
108 
109 
111 
112 
113 };
114 
115 template <class T, class I, class L>
116 LUnary<T, I, L>::LUnary(
117  const opengm::learning::Weights<T>& weights,
118  const LabelType numberOfLabels,
119  marray::Marray< size_t > weightIds,
120  marray::Marray< ValueType> features,
121  const bool makeFirstEntryConst
122 )
123 :
124 weights_(&weights),
125 numberOfLabels_(numberOfLabels),
126 offsets_(numberOfLabels*3),
127 weightIds_(),
128 features_()
129 {
130  const size_t pFeatDim = features.dimension();
131  const size_t pWeightIdDim = weightIds.dimension();
132 
133  OPENGM_CHECK_OP(weightIds.dimension(), ==, 2 , "wrong dimension");
134  OPENGM_CHECK_OP(weightIds.shape(0)+int(makeFirstEntryConst), ==, numberOfLabels , "wrong shape");
135 
136 
137  const size_t nWeights = weightIds.size();
138  weightIds_.resize(nWeights);
139 
140  const size_t nFeat = features.size();
141  features_.resize(nFeat);
142 
143 
144  OPENGM_CHECK_OP(features.dimension(), == , 1 , "feature dimension must be 1 ");
145  OPENGM_CHECK_OP(features.shape(0), == , weightIds.shape(1) , "feature dimension must be 1");
146 
147  // copy features
148  for(size_t fi=0; fi<nFeat; ++fi){
149  features_[fi] = features(fi);
150  }
151 
152  size_t nwForL = weightIds.shape(1);
153  size_t wOffset = 0;
154 
155  if(makeFirstEntryConst){
156 
157  OPENGM_CHECK_OP(numberOfLabels_-1, == , weightIds.shape(0),"internal error");
158 
159  offsets_[0*numberOfLabels_ + 0] = 0;
160  offsets_[1*numberOfLabels_ + 0] = 0;
161  offsets_[2*numberOfLabels_ + 0] = 0;
162 
163  for(LabelType l=1; l<numberOfLabels_; ++l){
164  offsets_[0*numberOfLabels_ + l] = nwForL;
165  offsets_[1*numberOfLabels_ + l] = wOffset;
166  offsets_[2*numberOfLabels_ + l] = 0;
167  // copy weight ids
168  for(size_t wi=0; wi<nwForL; ++wi){
169  weightIds_[wOffset + wi] = weightIds(l-1,wi);
170  }
171  wOffset += nwForL;
172  }
173  }
174  else{
175  OPENGM_CHECK_OP(numberOfLabels_, == , weightIds.shape(0),"internal error");
176  for(LabelType l=0; l<numberOfLabels_; ++l){
177 
178  offsets_[0*numberOfLabels_ + l] = nwForL;
179  offsets_[1*numberOfLabels_ + l] = wOffset;
180  offsets_[2*numberOfLabels_ + l] = 0;
181  // copy weight ids
182  for(size_t wi=0; wi<nwForL; ++wi){
183  weightIds_[wOffset + wi] = weightIds(l,wi);
184  }
185  wOffset += nwForL;
186  }
187  }
188 
189 }
190 
191 template <class T, class I, class L>
192 inline
194 (
195  const opengm::learning::Weights<T> & weights,
196  std::vector<FeaturesAndIndices<V, I> > featuresAndIndicesPerLabel
197 )
198 :
199 weights_(&weights),
200 numberOfLabels_(featuresAndIndicesPerLabel.size()),
201 offsets_(featuresAndIndicesPerLabel.size()*3),
202 weightIds_(),
203 features_()
204 {
205 
206  size_t fOffset = 0;
207  size_t wOffset = 0;
208 
209 
210  // fetch the offsets
211  for(size_t l=0; l<featuresAndIndicesPerLabel.size(); ++l){
212  const size_t nwForL = featuresAndIndicesPerLabel[l].weightIds.size();
213  const size_t nfForL = featuresAndIndicesPerLabel[l].features.size();
214  OPENGM_CHECK_OP(nwForL, == , nfForL, "number of features and weighs"
215  "must be the same for a given label within this overload of LUnary<T, I, L>::LUnary");
216 
217  offsets_[0*numberOfLabels_ + l] = nwForL;
218  offsets_[1*numberOfLabels_ + l] = wOffset;
219  offsets_[2*numberOfLabels_ + l] = fOffset;
220 
221  wOffset += nwForL;
222  fOffset += nfForL;
223  }
224 
225  weightIds_.resize(wOffset);
226  features_.resize(fOffset);
227 
228  // write weightIDs and features
229  for(size_t l=0; l<featuresAndIndicesPerLabel.size(); ++l){
230  const size_t nwForL = numWeightsForL(l);
231  for(size_t i=0; i<nwForL; ++i){
232  weightIds_[featureOffset(l)+i] = featuresAndIndicesPerLabel[l].weightIds[i];
233  features_[featureOffset(l)+i] = featuresAndIndicesPerLabel[l].features[i];
234  }
235  }
236 
237  // check that there are no duplicates
239  idSet.reserve(weightIds_.size());
240  idSet.insert(weightIds_.begin(), weightIds_.end());
241 
242  OPENGM_CHECK_OP(idSet.size(), == , weightIds_.size(), "weightIds has duplicates");
243 }
244 
245 
246 
247 template <class T, class I, class L>
248 template <class ITERATOR>
249 inline T
251 (
252  size_t weightNumber,
253  ITERATOR begin
254 ) const {
255  OPENGM_CHECK_OP(weightNumber,<,numberOfWeights(),
256  "weightNumber must be smaller than number of weights");
257  const LabelType l(*begin);
258  const size_t nwForL = numWeightsForL(l);
259  if(nwForL>0){
260  const size_t wiStart = weightIdOffset(l);
261  const size_t wiEnd = weightIdOffset(l)+nwForL;
262  if(weightNumber >= wiStart && weightNumber < wiEnd ){
263  const size_t wii = weightNumber - wiStart;
264  return features_[featureOffset(l) + wii];
265  }
266  }
267  return static_cast<ValueType>(0);
268 }
269 
270 template <class T, class I, class L>
271 template <class ITERATOR>
272 inline T
274 (
275  ITERATOR begin
276 ) const {
277 
278  //std::cout<<"LUnary::operator()\n";
279  //OPENGM_CHECK_OP( int(weights_==NULL),==,int(false),"foo");
280  T val = 0;
281  const LabelType l(*begin);
282  const size_t nwForL = numWeightsForL(l);
283  //std::cout<<"nw for l "<<nwForL<<"\n";
284  //std::cout<<"wsize "<<weights_->size()<<"\n";
285 
286  for(size_t i=0; i<nwForL; ++i){
287  //std::cout<<" i "<<i<<"\n";
288  //OPENGM_CHECK_OP(weightIdOffset(l)+i,<,weightIds_.size(),"foo");
289  //OPENGM_CHECK_OP(featureOffset(l)+i,<,features_.size(),"foo");
290  const size_t wi = weightIds_[weightIdOffset(l)+i];
291  //OPENGM_CHECK_OP(wi,<,weights_->size(),"foo");
292 
293  val += weights_->getWeight(wi) * features_[featureOffset(l)+i];
294  }
295  //d::cout<<"LUnary::return operator()\n";
296  return val;
297 }
298 
299 
300 template <class T, class I, class L>
301 inline L
303 (
304  const size_t i
305 ) const {
306  return numberOfLabels_;
307 }
308 
309 template <class T, class I, class L>
310 inline size_t
312  return 1;
313 }
314 
315 template <class T, class I, class L>
316 inline size_t
318  return numberOfLabels_;
319 }
320 
321 } // namespace learnable
322 } // namespace functions
323 
324 
326 template<class T, class I, class L>
328 public:
330 
331  static size_t indexSequenceSize(const opengm::functions::learnable::LUnary<T, I, L>&);
332  static size_t valueSequenceSize(const opengm::functions::learnable::LUnary<T, I, L>&);
333  template<class INDEX_OUTPUT_ITERATOR, class VALUE_OUTPUT_ITERATOR>
334  static void serialize(const opengm::functions::learnable::LUnary<T, I, L>&, INDEX_OUTPUT_ITERATOR, VALUE_OUTPUT_ITERATOR);
335  template<class INDEX_INPUT_ITERATOR, class VALUE_INPUT_ITERATOR>
336  static void deserialize( INDEX_INPUT_ITERATOR, VALUE_INPUT_ITERATOR, opengm::functions::learnable::LUnary<T, I, L>&);
337 };
338 
339 template<class T, class I, class L>
341  enum ID {
343  };
344 };
345 
346 template<class T, class I, class L>
347 inline size_t
349 (
351 ) {
352 
353  size_t size = 0;
354  size += 1; // numberOfLabels
355  size += 1; // numberOfWeights
356  size += 1; // numberOfFeatures
357 
358  size += 3*src.shape(0); // offsets serialization
359  size += src.weightIds_.size(); // weight id serialization
360 
361  return size;
362 }
363 
364 template<class T, class I, class L>
365 inline size_t
367 (
369 ) {
370  return src.features_.size(); // feature serialization
371 }
372 
373 template<class T, class I, class L>
374 template<class INDEX_OUTPUT_ITERATOR, class VALUE_OUTPUT_ITERATOR >
375 inline void
377 (
379  INDEX_OUTPUT_ITERATOR indexOutIterator,
380  VALUE_OUTPUT_ITERATOR valueOutIterator
381 ) {
382 
386  // number of labels
387  *indexOutIterator = src.shape(0);
388  ++indexOutIterator;
389 
390  // number of weights
391  *indexOutIterator = src.weightIds_.size();
392  ++indexOutIterator;
393 
394  // number of features
395  *indexOutIterator = src.features_.size();
396  ++indexOutIterator;
397 
398  // offset serialization
399  for(size_t i=0; i<src.offsets_.size(); ++i){
400  *indexOutIterator = src.offsets_[i];
401  ++indexOutIterator;
402  }
403 
404  // weight id serialization
405  for(size_t i=0; i<src.weightIds_.size(); ++i){
406  *indexOutIterator = src.weightIds_[i];
407  ++indexOutIterator;
408  }
409 
413  // feature serialization
414  for(size_t i=0; i<src.features_.size(); ++i){
415  *valueOutIterator = src.features_[i];
416  ++valueOutIterator;
417  }
418 }
419 
420 template<class T, class I, class L>
421 template<class INDEX_INPUT_ITERATOR, class VALUE_INPUT_ITERATOR >
422 inline void
424 (
425  INDEX_INPUT_ITERATOR indexInIterator,
426  VALUE_INPUT_ITERATOR valueInIterator,
428 ) {
429 
430 
431 
435  // number of labels
436  dst.numberOfLabels_ = *indexInIterator;
437  ++indexInIterator;
438  // resize offset accordingly
439  dst.offsets_.resize(3 * dst.numberOfLabels_);
440 
441 
442  // number of weights
443  const size_t nW =*indexInIterator;
444  ++indexInIterator;
445  // resize weightIds accordingly
446  dst.weightIds_.resize(nW);
447 
448  // number of features
449  const size_t nF = *indexInIterator;
450  ++indexInIterator;
451  // resize weightIds accordingly
452  dst.features_.resize(nF);
453 
454  // offset deserialization
455  for(size_t i=0; i<dst.offsets_.size(); ++i){
456  dst.offsets_[i] = *indexInIterator;
457  ++indexInIterator;
458  }
459 
460  // weight id deserialization
461  for(size_t i=0; i<dst.weightIds_.size(); ++i){
462  dst.weightIds_[i] = *indexInIterator;
463  ++indexInIterator;
464  }
465 
469  // feature deserialization
470  for(size_t i=0; i<dst.features_.size(); ++i){
471  dst.features_[i] = *valueInIterator;
472  ++valueInIterator;
473  }
474 }
475 
476 } // namespace opengm
477 
478 #endif // #ifndef OPENGM_LEARNABLE_FUNCTION_HXX
The OpenGM namespace.
Definition: config.hxx:43
Fallback implementation of member functions of OpenGM functions.
T weightGradient(size_t, ITERATOR) const
Definition: lunary.hxx:251
size_t featureOffset(const LabelType l) const
Definition: lunary.hxx:98
size_type size() const
number of elements of the set
const opengm::learning::Weights< T > * weights_
Definition: lunary.hxx:102
ValueType getWeight(const size_t pi) const
Definition: weights.hxx:66
L shape(const size_t) const
Definition: lunary.hxx:303
I weightIndex(const size_t weightNumber) const
Definition: lunary.hxx:80
const size_t FUNCTION_TYPE_ID_OFFSET
User-defined function have ids smaller than FUNCTION_TYPE_ID_OFFSET.
size_t numWeightsForL(const LabelType l) const
Definition: lunary.hxx:92
std::vector< IndexType > offsets_
Definition: lunary.hxx:105
std::vector< size_t > weightIds_
Definition: lunary.hxx:106
std::pair< const_iterator, bool > insert(const value_type &)
void reserve(const size_t size)
const size_t dimension() const
Get the dimension.
Definition: marray.hxx:1711
std::vector< ValueType > features_
Definition: lunary.hxx:107
size_t weightIdOffset(const LabelType l) const
Definition: lunary.hxx:95
#define OPENGM_CHECK_OP(A, OP, B, TXT)
Definition: submodel2.hxx:24
Runtime-flexible multi-dimensional array.
Definition: marray.hxx:52
void setWeights(const opengm::learning::Weights< T > &weights) const
Definition: lunary.hxx:72
const size_t shape(const size_t) const
Get the shape in one dimension.
Definition: marray.hxx:1725
opengm::functions::learnable::LUnary< T, I, L >::ValueType ValueType
Definition: lunary.hxx:329
const size_t size() const
Get the number of data items.
Definition: marray.hxx:1698