OpenGM  2.3.x
Discrete Graphical Model Library
operator.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_FUNCTION_LEVEL_OPERATOR_HXX
3 #define OPENGM_FUNCTION_LEVEL_OPERATOR_HXX
4 
5 #include <vector>
6 #include <set>
7 
8 #include "opengm/opengm.hxx"
12 
13 namespace opengm {
14 
16 
19 class ComputeViAndAShape {
20 public:
21  typedef std::vector<size_t> ViSequenceType;
22 
23  template<class A, class B ,class VI_A,class VI_B,class VI_C,class SHAPE_C>
24  static inline void computeViandShape
25  (
26  const VI_A & via,
27  const VI_B & vib,
28  VI_C & vic,
29  const A& a,
30  const B& b ,
31  SHAPE_C & shapeC
32  ) {
33  OPENGM_ASSERT(a.dimension() == via.size());
34  OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
35  OPENGM_ASSERT(b.dimension() == vib.size());
36  OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
37  shapeC.clear();
38  vic.clear();
39  const size_t dimA = via.size();
40  const size_t dimB = vib.size();
41  vic.reserve(dimA+dimB);
42  shapeC.reserve(dimA+dimB);
43  if(via.size() == 0 && vib.size() == 0) {
44  }
45  else if(via.size() == 0) {
46  vic.assign(vib.begin(),vib.end());
47  for(size_t i=0;i<dimB;++i) {
48  shapeC.push_back(b.shape(i));
49  }
50  }
51  else if(vib.size() == 0) {
52  vic.assign(via.begin(),via.end());
53  for(size_t i=0;i<dimA;++i) {
54  shapeC.push_back(a.shape(i));
55  }
56  }
57  else {
58  size_t ia = 0;
59  size_t ib = 0;
60  bool first = true;
61  while(ia<dimA || ib<dimB) {
62  if(first==true) {
63  first=false;
64  if(via[ia]<=vib[ib]) {
65  vic.push_back(via[ia]);
66  shapeC.push_back(a.shape(ia));
67  ++ia;
68  }
69  else{
70  vic.push_back(vib[ib]);
71  shapeC.push_back(b.shape(ib));
72  ++ib;
73  }
74  }
75  else if(ia>=dimA) {
76  if(vic.back()!=vib[ib]) {
77  vic.push_back(vib[ib]);
78  shapeC.push_back(b.shape(ib));
79  }
80  ++ib;
81  }
82  else if(ib>=dimB) {
83  if(vic.back()!=via[ia]) {
84  vic.push_back(via[ia]);
85  shapeC.push_back(a.shape(ia));
86  }
87  ++ia;
88  }
89  else if(via[ia]<=vib[ib]) {
90  if(vic.back()!=via[ia] ) {
91  vic.push_back(via[ia]);
92  shapeC.push_back(a.shape(ia));
93  }
94  ++ia;
95  }
96  else{
97  if(vic.back()!=vib[ib] ) {
98  vic.push_back(vib[ib]);
99  shapeC.push_back(b.shape(ib));
100  }
101  ++ib;
102  }
103  }
104  OPENGM_ASSERT(ia == dimA);
105  OPENGM_ASSERT(ib == dimB);
106  }
107  }
108 };
109 
111 template<class A, class B, class C, class OP>
112 class BinaryOperationImpl
113 {
114 public:
115  template<class VI_A,class VI_B,class VI_C>
116  static void op(const A& , const B& , C& , const VI_A& , const VI_B & , VI_C & , OP);
117 };
118 
120 template<class A, class B, class OP>
121 class BinaryOperationInplaceImpl
122 {
123 public:
124  template<class VI_A,class VI_B>
125  static void op(A& , const B& , VI_A& , const VI_B& , OP);
126 };
127 
129 template<class A, class B, class OP>
130 class UnaryOperationImpl {
131 public:
132  static void op(const A& a, B& b, OP);
133 };
134 
136 template<class A, class OP>
137 class UnaryOperationInplaceImpl {
138 public:
139  static void op(A& a, OP);
140 };
141 
143 template<class A, class B, class C, class OP>
144 template<class VI_A,class VI_B,class VI_C>
145 void BinaryOperationImpl<A, B, C, OP>::op
146 (
147  const A& a,
148  const B& b,
149  C& c,
150  const VI_A & via,
151  const VI_B & vib,
152  VI_C & vic,
153  OP op
154 ) {
155  OPENGM_ASSERT(a.dimension() == via.size());
156  OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
157  OPENGM_ASSERT(b.dimension() == vib.size());
158  OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
159  // clear c
160  c.assign();
161  // compute output vi's and shape of c
163  ComputeViAndAShape::computeViandShape(via, vib, vic, a, b, shapeC);
164  OPENGM_ASSERT(shapeC.size() == vic.size());
165  // reshape c
166  c.resize(shapeC.begin(), shapeC.end());
167  // get dimensions and number of Elements in c
168  const size_t dimA = a.dimension();
169  const size_t dimB = b.dimension();
170  //const size_t dimC = c.dimension();
171  const size_t numElemmentC = c.size();
173  if(dimA != 0 && dimB != 0) {
174  opengm::TripleShapeWalker<FIterType > shapeWalker(shapeC.begin(),shapeC.size(), vic, via, vib);
175  for(size_t i=0; i<numElemmentC; ++i) {
176  OPENGM_ASSERT(a.dimension() == shapeWalker.coordinateTupleA().size());
177  OPENGM_ASSERT(b.dimension() == shapeWalker.coordinateTupleB().size());
178  OPENGM_ASSERT(c.dimension() == shapeWalker.coordinateTupleAB().size());
179  c(shapeWalker.coordinateTupleAB().begin()) = op(a(shapeWalker.coordinateTupleA().begin()), b(shapeWalker.coordinateTupleB().begin()));
180  ++shapeWalker;
181  }
182  }
183  else if(dimA == 0 && dimB == 0) {
184  const size_t scalarIndex=0;
185  c.resize(&scalarIndex, &scalarIndex+1);
186  c(&scalarIndex) = op(a(&scalarIndex), b(&scalarIndex));
187  }
188  else if(dimA == 0) {
189  opengm::ShapeWalker<FIterType > shapeWalker(shapeC.begin(),shapeC.size());
190  const size_t scalarIndex=0;
191  for(size_t i=0; i<numElemmentC; ++i) {
192  c(shapeWalker.coordinateTuple().begin()) = op(a(&scalarIndex), b(shapeWalker.coordinateTuple().begin()));
193  ++shapeWalker;
194  }
195  }
196  else { // DimB == 0
197  opengm::ShapeWalker<FIterType > shapeWalker(shapeC.begin(),shapeC.size());
198  const size_t scalarIndex=0;
199  for(size_t i=0; i<numElemmentC; ++i) {
200  c(shapeWalker.coordinateTuple().begin()) = op(a(shapeWalker.coordinateTuple().begin()), b(&scalarIndex));
201  ++shapeWalker;
202  }
203  }
204  OPENGM_ASSERT(a.dimension() == via.size());
205  OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
206  OPENGM_ASSERT(b.dimension() == vib.size());
207  OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
208  OPENGM_ASSERT(c.dimension() == vic.size());
209  OPENGM_ASSERT(c.dimension() != 0 || (c.dimension() == 0 && c.size() == 1));
210 }
211 
213 template<class A, class B, class OP>
214 template<class VI_A,class VI_B>
215 void BinaryOperationInplaceImpl<A, B, OP>::op
216 (
217  A& a,
218  const B& b,
219  VI_A & via,
220  const VI_B & vib,
221  OP op
222 )
223 {
224  OPENGM_ASSERT(a.dimension() == via.size());
225  OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
226  OPENGM_ASSERT(b.dimension() == vib.size());
227  OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
228  // compute output vi's and shape of a(new)
231  ComputeViAndAShape::computeViandShape(via, vib, viaNew, a, b, shapeANew);
232  OPENGM_ASSERT(shapeANew.size() == viaNew.size());
233  // in-place
234  if(viaNew.size() == via.size()) {
235  if(viaNew.size() != 0) {
236  if(vib.size() != 0) {
237  const size_t numElementInA = a.size();
238  opengm::DoubleShapeWalker<opengm::FastSequence<size_t>::const_iterator > shapeWalker(shapeANew.begin(),shapeANew.size(), viaNew, vib);
239  for(size_t i=0; i<numElementInA; ++i) {
240  a(shapeWalker.coordinateTupleAB().begin()) = op(a(shapeWalker.coordinateTupleAB().begin()), b(shapeWalker.coordinateTupleA().begin()));
241  ++shapeWalker;
242  }
243  }
244  else {
245  const size_t numElementInA = a.size();
246  opengm::DoubleShapeWalker<opengm::FastSequence<size_t>::const_iterator > shapeWalker(shapeANew.begin(),shapeANew.size(), viaNew, vib); const size_t scalarIndex = 0;
247  for(size_t i=0; i<numElementInA; ++i) {
248  a(shapeWalker.coordinateTupleAB().begin()) = op(a(shapeWalker.coordinateTupleAB().begin()), b(&scalarIndex));
249  ++shapeWalker;
250  }
251  }
252  }
253  else {
254  const size_t scalarIndex=0;
255  a.resize(&scalarIndex, &scalarIndex+1);
256  a(&scalarIndex) = op(a(&scalarIndex), b(&scalarIndex));
257  via.assign(viaNew.begin(),viaNew.end());
258  }
259  }
260  // not inplace
261  else {
262  A aNew;
263  BinaryOperationImpl<A, B, A, OP>::op(a, b, aNew, via, vib, viaNew, op);
264  a = aNew;
265  via.assign(viaNew.begin(),viaNew.end());
266  }
267  OPENGM_ASSERT(a.dimension() == via.size());
268  OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
269  OPENGM_ASSERT(b.dimension() == vib.size());
270  OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
271 }
272 
274 template<class A, class B, class OP>
275 void UnaryOperationImpl<A, B, OP>::op
276 (
277  const A& a,
278  B& b,
279  OP op
280 )
281 {
282  OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
283  // clear b
284  b.assign();
285  // get dimensions and number of Elements in b
286  const size_t dimA = a.dimension();
287  if(dimA != 0) {
288  // reshape b
289  typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
290  ShapeIterType shapeABegin(a, 0);
291  ShapeIterType shapeAEnd(a, dimA);
292  b.resize(shapeABegin, shapeAEnd);
293  opengm::ShapeWalker< ShapeIterType> shapeWalker(shapeABegin, dimA);
294  const size_t numElemmentA = a.size();
295  for(size_t i=0; i<numElemmentA; ++i) {
296  b(shapeWalker.coordinateTuple().begin()) = op(a(shapeWalker.coordinateTuple().begin()));
297  ++shapeWalker;
298  }
299  }
300  else {
301  const size_t scalarIndex=0;
302  b.resize(&scalarIndex, &scalarIndex+1);
303  b(&scalarIndex) = op(a(&scalarIndex));
304  }
305 }
306 
308 template<class A, class OP>
309 void UnaryOperationInplaceImpl<A, OP>::op
310 (
311  A& a,
312  OP op
313 )
314 {
315  OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
316  const size_t dimA = a.dimension();
317  if(dimA != 0) {
318  typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
319  ShapeIterType shapeABegin(a, 0);
320  opengm::ShapeWalker< ShapeIterType> shapeWalker(shapeABegin, dimA);
321  const size_t numElemmentA = a.size();
322  for(size_t i=0; i<numElemmentA; ++i) {
323  a(shapeWalker.coordinateTuple().begin()) = op(a(shapeWalker.coordinateTuple().begin()));
324  ++shapeWalker;
325  }
326  }
327  else {
328  const size_t scalarIndex=0;
329  a(&scalarIndex) = op(a(&scalarIndex));
330  }
331 }
332 
334 
335 } // namespace opengm
336 
337 #endif // #ifndef OPENGM_FUNCTION_LEVEL_OPERATOR_HXX
The OpenGM namespace.
Definition: config.hxx:43
size_t size() const
size
Vector that stores values on the stack if size is smaller than MAX_STACK.
T const * end() const
end iterator
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
T const * begin() const
begin iterator