aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
LpInterface.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 #ifndef __LP_INTERFACE__H__
23 #define __LP_INTERFACE__H__
24 
25 /**
26  * @file
27  * @brief Class representing a polytope ( credal set ) by a set of linear
28  * constraints
29  * @author Matthieu HOURBRACQ and Pierre-Henri WUILLEMIN(@LIP6)
30  */
31 
32 #include <iostream>
33 #include <sstream>
34 #include <string>
35 
36 #include <agrum/CN/polytope/LrsWrapper.h>
37 #include <agrum/tools/core/hashFunc.h>
38 #include <agrum/tools/core/hashTable.h>
39 #include <agrum/tools/core/utils_misc.h>
40 
41 namespace gum {
42  namespace credal {
43  namespace lp {
44 
45  class LpCol;
46  class LpRow;
47  template < typename GUM_SCALAR >
48  class LpInterface;
49  class LpExpr;
50 
51  /**
52  * @class LpCol
53  * @headerfile LpInterface.h <agrum/CN/LpInterface.h>
54  * @brief Class representing a variable ( a column ) of a linear program,
55  * i.e. a
56  * dimension of the problem.
57  * @ingroup cn_group
58  * @author Matthieu HOURBRACQ and Pierre-Henri WUILLEMIN(@LIP6)
59  */
60  class LpCol {
61  public:
62  /// @name Constructor / Destructor
63  /// @{
64 
65  /**
66  * @brief Default constructor.
67  * @param id The id of the variable.
68  */
69  explicit LpCol(unsigned int id);
70 
71  /**
72  * @brief Default copy constructor.
73  * @param col The constant reference to the variable to copy.
74  */
75  LpCol(const LpCol& col);
76 
77  /** @brief Default destructor. */
78  ~LpCol();
79 
80  /// @}
81 
82  /**
83  * @brief %Variable id accessor.
84  * @return The id of the variable.
85  */
86  unsigned int id() const;
87 
88  /// @name Operators overload
89  /// @{
90 
91  /**
92  * @brief Test of ordering \c < between two variables.
93  *
94  * For use with maps, hashTable etc
95  * @param col The constant reference to the variable to compare to this (
96  *the
97  *caller ).
98  * @return \c True if this id is smaller than \c col id, false otherwise.
99  */
100  bool operator<(const LpCol& col) const;
101 
102  /**
103  * @brief Test of equality \c == between two variables.
104  *
105  * For use with maps, hashTable etc
106  * @param col The constant reference to the variable to compare to this (
107  *the
108  *caller ).
109  * @return \c True if this id is equals to \c col id, false otherwise.
110  */
111  bool operator==(const LpCol& col) const;
112 
113  /**
114  * @brief Opposite of equality \c != test between two variables.
115  *
116  * For use with maps, hashTable etc
117  * @param col The constant reference to the variable to compare to this (
118  *the
119  *caller ).
120  * @return \c True if this id is not the same than \c col id, false
121  *otherwise.
122  */
123  bool operator!=(const LpCol& col) const;
124 
125  /**
126  * @brief Assignment operator \c = by copy.
127  * @param col The constant reference to the variable to copy in this (
128  * the
129  * caller ).
130  * @return The address of the caller.
131  */
132  LpCol& operator=(const LpCol& col);
133 
134  /**
135  * @brief Overload of \c << to use with output streams ( such as
136  * std::cout <<
137  * ).
138  * @param out The reference to the caller, i.e. left side of \c <<.
139  * @param col The constant reference to the variable whose representation
140  * we
141  * want.
142  * @return The address of the caller.
143  */
144  friend std::ostream&
145  operator<<(std::ostream& out,
146  const LpCol& col); // calls col.toString(),
147  // friend is useless but
148  // good for documentation
149  // purpose
150 
151  /// @}
152 
153  /**
154  * @brief Get the string representation of a calling variable.
155  * @return The string representation of the calling variable.
156  */
157  std::string toString() const;
158 
159  protected:
160  private:
161  /** @brief %Variable id. */
162  unsigned int id__;
163  };
164 
165  } // end of namespace lp
166 
167  } // end of namespace credal
168 
169 } // end of namespace gum
170 
171 namespace gum {
172 
173  /**
174  * @class gum::HashFunc
175  * @headerfile LpInterface.h <agrum/CN/LpInterface.h>
176  * @brief Class template representing hashing function of \c LpCol. To use
177  * aGrUM
178  * hashTable.
179  */
180  template <>
181  class HashFunc< credal::lp::LpCol >: public HashFuncBase< credal::lp::LpCol > {
182  public:
183  /**
184  * @brief Returns the value of a key as a Size.
185  * @param key The value to return as a Size.
186  * @return Returns the value of a key as a Size.
187  */
188  static Size castToSize(const credal::lp::LpCol& key);
189 
190  /**
191  * @brief Overload of operator () to compute hash of a variable \c LpCol.
192  * @param key The constant reference to the variable whose hash we want to
193  * compute.
194  */
195  virtual Size operator()(const credal::lp::LpCol& key) const override final;
196  };
197 } // end of namespace gum
198 
199 namespace gum {
200  namespace credal {
201  namespace lp {
202 
203  /**
204  * @class LpExpr
205  * @headerfile LpInterface.h <agrum/CN/LpInterface.h>
206  * @brief Class representing a linear expression.
207  * @author Matthieu HOURBRACQ and Pierre-Henri WUILLEMIN(@LIP6)
208  */
209  class LpExpr {
210  friend class LpRow;
211  template < typename GUM_SCALAR >
212  friend class LpInterface;
213 
214  public:
215  /// @name Constructors / Destructors
216  /// @{
217 
218  /** @brief Default constructor. */
219  LpExpr();
220 
221  /**
222  * @brief Copy constructor.
223  * @param expr The constant reference to the expression to copy.
224  */
225  LpExpr(const LpExpr& expr);
226 
227  /**
228  * @brief Copy constructor. Makes a ( partial ) copy.
229  * @param expr The constant reference to the expression to copy.
230  * @param copyLeft \c True if we want to copy left side of \c expr, \c
231  * False
232  * otherwise.
233  * @param copyMiddle \c True if we want to copy middle side of \c expr,
234  * \c
235  * False otherwise.
236  * @param copyRight \c True if we want to copy right side of \c expr, \c
237  * False
238  * otherwise.
239  */
240  LpExpr(const LpExpr& expr, bool copyLeft, bool copyMiddle, bool copyRight);
241 
242  /**
243  * @brief Move copy constructor from temporary.
244  *
245  * Swap ressources between the temporary \c expr and the caller instead
246  *of
247  *copying the temporary.
248  * @param expr The temporary expression to move to this.
249  */
250  LpExpr(LpExpr&& expr);
251 
252  /**
253  * @brief Move copy constructor from temporary. Makes ( partial ) moves.
254  *
255  * @warning Proceed with care; partial moves are dangerous because the
256  *object
257  *being moved may still briefly exist after being moved and could be used
258  *afterward.
259  *
260  * @param expr The temporary expression to ( partially ) move to this.
261  * @param copyLeft \c True if we want to copy left side of \c expr, \c
262  *False
263  *otherwise.
264  * @param copyMiddle \c True if we want to copy middle side of \c expr,
265  *\c
266  *False otherwise.
267  * @param copyRight \c True if we want to copy right side of \c expr, \c
268  *False
269  *otherwise.
270  */
271  LpExpr(LpExpr&& expr, bool copyLeft, bool copyMiddle, bool copyRight);
272 
273  /** @brief Default destructor. */
274  ~LpExpr();
275 
276  /// @}
277 
278  /// @name Assignment operators =
279  /// @{
280 
281  /**
282  * @brief Assignment operator \c = with a variable.
283  * @param rhs the constant reference to the variable to form an
284  * expression
285  * with.
286  * @return The address of the calling expression.
287  */
288  LpExpr& operator=(const LpCol& rhs);
289 
290  /**
291  * @brief Assignment operator \c = with another expression, by copy.
292  * @param rhs the constant reference to the expression to copy.
293  * @return The address of the calling expression.
294  */
295  LpExpr& operator=(const LpExpr& rhs);
296 
297  /**
298  * @brief Assignment operator \c = with another expression, by move.
299  * @param rhs the expression to move to this.
300  * @return The address of the calling expression.
301  */
302  LpExpr& operator=(LpExpr&& rhs);
303 
304  /**
305  * @brief Assignment operator \c = with a scalar.
306  * @tparam SCALAR A scalar type ( integer or float ( any precision ) ).
307  * @param rhs the constant reference to the scalar to form an expression
308  * with.
309  * @return The address of the calling expression.
310  */
311  template < typename SCALAR >
312  LpExpr& operator=(const SCALAR& rhs);
313 
314  /// @}
315 
316  /// @name Compound assignment operators +=
317  /// @{
318 
319  /**
320  * @brief Compound assignment operator \c += with a variable.
321  * @param rhs the constant reference to the variable to add to the
322  * calling
323  * expression.
324  * @return The reference of the calling expression.
325  */
326  LpExpr& operator+=(const LpCol& rhs);
327 
328  /**
329  * @brief Compound assignment operator \c += with another expression.
330  * @param rhs the constant reference to the expression to add to the
331  * calling
332  * expression.
333  * @return The reference of the calling expression.
334  */
335  LpExpr& operator+=(const LpExpr& rhs);
336 
337  /**
338  * @brief Compound assignment operator \c += with another temporary
339  * expression.
340  * @param rhs the temporary expression to add to the calling expression.
341  * @return The reference of the calling expression.
342  */
343  LpExpr& operator+=(LpExpr&& rhs);
344 
345  /**
346  * @brief Compound assignment operator \c += with a scalar.
347  * @tparam SCALAR A scalar type ( integer or float ( any precision ) ).
348  * @param rhs the constant reference to the scalar to add to the calling
349  * expression.
350  * @return The reference of the calling expression.
351  */
352  template < typename T >
353  LpExpr& operator+=(const T& rhs);
354 
355  /// @}
356 
357  /// @name Compound assignment operators -=
358  /// @{
359 
360  /**
361  * @brief Compound assignment operator \c -= with a variable.
362  * @param rhs the constant reference to the variable to substract from
363  * the
364  * calling expression.
365  * @return The reference of the calling expression.
366  */
367  LpExpr& operator-=(const LpCol& rhs);
368 
369  /**
370  * @brief Compound assignment operator \c -= with another expression.
371  * @param rhs the constant reference to the expression to substract from
372  * the
373  * calling expression.
374  * @return The reference of the calling expression.
375  */
376  LpExpr& operator-=(const LpExpr& rhs);
377 
378  /**
379  * @brief Compound assignment operator \c -= with a salar.
380  * @tparam SCALAR A scalar type ( integer or float ( any precision ) ).
381  * @param rhs the constant reference to the scalar to substract from the
382  * calling expression.
383  * @return The reference of the calling expression.
384  */
385  template < typename T >
386  LpExpr& operator-=(const T& rhs);
387 
388  /// @}
389 
390  /** @brief Clear all data of the calling expression as if it was
391  * constructed.
392  */
393  void clear();
394 
395  /**
396  * @brief Get the string representation of a calling expression.
397  * @return The string representation of the calling expression.
398  */
399  std::string toString() const;
400 
401  /// @name Helper static methods for operations
402  /// @{
403  template < typename T1, typename T2 >
404  static LpExpr lessThan(T1&& lhs, T2&& rhs);
405  template < typename SCALAR >
406  static LpExpr multiply(const SCALAR& lhs, const LpCol& rhs);
407  /// @}
408 
409  protected:
410  private:
411  /** @brief \c True if this expression has a non-empty left side L : L <=
412  * M <=
413  * R . \c False otherwise. */
414  bool ileft__;
415  /** @brief \c True if this expression has a non-empty middle side M (
416  * the
417  * default ) : L <= M <= R . \c False otherwise. */
418  bool imiddle__;
419  /** @brief \c True if this expression has a non-empty right side R : L
420  * <= M
421  * <= R . \c False otherwise. */
422  bool iright__;
423 
424  /** @brief The constant on the left side L : L <= M <= R */
425  double lValue__;
426  /** @brief The constant on the middle side L : L <= M <= R */
427  double mValue__;
428  /** @brief The constant on the right side L : L <= M <= R */
429  double rValue__;
430 
431  /** @brief The coefficients of each variable on the left side L : L <= M
432  * <=
433  * R. If a variable is not present, it's coefficient is 0. */
434  HashTable< LpCol, double >* lCoeffs__;
435  /** @brief The coefficients of each variable on the middle side L : L <=
436  * M <=
437  * R. If a variable is not present, it's coefficient is 0. */
438  HashTable< LpCol, double >* mCoeffs__;
439  /** @brief The coefficients of each variable on the right side L : L <=
440  * M <=
441  * R. If a variable is not present, it's coefficient is 0. */
442  HashTable< LpCol, double >* rCoeffs__;
443 
444  /// @name Used by static method LpExpr::LessThan<T1,T2> and by operator
445  /// <=
446  /// @{
447 
448  /**
449  * @brief %Set the side of the calling expression, from LEFT TO RIGHT : L
450  * <= M
451  * <= R.
452  * @param from the constant reference to the variable ( the side ) to put
453  * on
454  * the first empty side met, starting at left.
455  */
456  void addSide__(const LpCol& from);
457 
458  /**
459  * @brief Copy an expression to a side of the calling expression, from
460  * LEFT TO
461  * RIGHT : L <= M <= R.
462  * @param from the constant reference to the expression ( the side ) to
463  * copy
464  * on the first empty side met, starting at left.
465  */
466  void addSide__(const LpExpr& from);
467 
468  /**
469  * @brief Move an expression to a side of the calling expression, from
470  * LEFT TO
471  * RIGHT : L <= M <= R.
472  * @param from the expression ( the side ) to move on the first empty
473  * side
474  * met, starting at left.
475  */
476  void addSide__(LpExpr&& from);
477 
478  /**
479  * @brief %Set the side of the calling expression, from LEFT TO RIGHT : L
480  * <= M
481  * <= R.
482  * @tparam SCALAR A scalar type ( integer or float ( any precision ) ).
483  * @param from the constant reference to the scalar ( the side ) to put
484  * on the
485  * first empty side met, starting at left.
486  */
487  template < typename SCALAR >
488  void addSide__(const SCALAR& from);
489 
490  /// @}
491  };
492 
493  /**
494  * @class LpRow
495  * @headerfile LpInterface.h <agrum/CN/LpInterface.h>
496  * @brief Class representing a row of the linear program, i.e. an
497  * inequality.
498  * @author Matthieu HOURBRACQ and Pierre-Henri WUILLEMIN(@LIP6)
499  */
500  class LpRow {
501  template < typename GUM_SCALAR >
502  friend class LpInterface;
503 
504  public:
505  /// @name Constructors / Destructors
506  /// @{
507 
508  /**
509  * @brief Constructor from an expression and the address of the vector of
510  * variables of the problem.
511  * @param expr the constant reference to the expression to convert into
512  * rows (
513  * inequalities ).
514  * @param cols the constant reference to the vector of variables of the
515  * problem.
516  */
517  LpRow(const LpExpr& expr, const std::vector< LpCol >& cols);
518 
519  /**
520  * @brief Move constructor from a temporary expression and the address of
521  * the
522  * vector of variables of the problem.
523  * @param expr the temporary expression to move into rows ( inequalities
524  * ).
525  * @param cols the constant reference to the vector of variables of the
526  * problem.
527  */
528  LpRow(LpExpr&& expr, const std::vector< LpCol >& cols);
529 
530  /**
531  * @brief Copy constructor.
532  * @param row The constant reference to the row to be copied.
533  */
534  LpRow(const LpRow& row);
535 
536  /**
537  * @brief Move copy constructor from temporary.
538  * @param row The temporary row to be copied.
539  */
540  LpRow(LpRow&& row);
541 
542  /** @brief Default destructor. */
543  ~LpRow();
544 
545  /// @}
546 
547  /// @name Assignment operators
548  /// @{
549 
550  /**
551  * @brief
552  * @param row The constant reference to the row to be copied.
553  */
554  LpRow& operator=(const LpRow& row);
555  /**
556  * @brief
557  * @param row The temporary row to be moved to this.
558  */
559  LpRow& operator=(LpRow&& row);
560 
561  /// @}
562 
563  /**
564  * @brief Overload of \c << to use with output streams ( such as
565  * std::cout <<
566  * ).
567  * @param out the reference to the caller, i.e. left side of \c <<.
568  * @param row the constant reference to the row whose representation we
569  * want.
570  * @return The address of the caller.
571  */
572  friend std::ostream&
573  operator<<(std::ostream& out,
574  const LpRow& row); // calls row.toString(),
575  // friend is useless but
576  // good for documentation
577  // purpose
578 
579  /**
580  * @brief Get the string representation of a calling row.
581  * @return The string representation of the calling row.
582  */
583  std::string toString() const;
584 
585  protected:
586  private:
587  /** @brief The constant of the linear inequality. */
588  double cste__;
589 
590  /** @brief The coefficients of the variables of the linear inequality.
591  */
592  HashTable< LpCol, double >* coeffs__;
593 
594  }; // end of class LpRow
595 
596  /**
597  * @class LpInterface
598  * @headerfile LpInterface.h <agrum/CN/LpInterface.h>
599  * @brief Class representing a linear program.
600  * @author Matthieu HOURBRACQ and Pierre-Henri WUILLEMIN(@LIP6)
601  */
602  template < typename GUM_SCALAR >
603  class LpInterface {
604  public:
605  /// @name Constructor / Destructor
606  /// @{
607 
608  /** @brief Default constructor, empty problem. */
609  LpInterface();
610 
611  /**
612  * @brief Copy constructor.
613  * @param from The LpInterface to be copied.
614  */
615  LpInterface(const LpInterface< GUM_SCALAR >& from);
616 
617  /**
618  * @brief Move copy constructor.
619  * @param from The temporary LpInterface to be moved.
620  */
621  LpInterface(LpInterface< GUM_SCALAR >&& from);
622 
623  /** @brief Default destructor. */
624  ~LpInterface();
625 
626  /// @}
627 
628  /// @name Compound assignment operator
629  /// @{
630 
631  /**
632  * @brief Copy compound assignment.
633  * @param from The LpInterface to be copied.
634  */
635  LpInterface< GUM_SCALAR >&
636  operator=(const LpInterface< GUM_SCALAR >& from);
637 
638  /**
639  * @brief Move coumpound assignment.
640  * @param from The temporary LpInterface to be moved.
641  */
642  LpInterface< GUM_SCALAR >& operator=(LpInterface< GUM_SCALAR >&& from);
643 
644  /// @}
645 
646  /**
647  * @brief Overload of \c << to use with output streams ( such as
648  * std::cout <<
649  * ).
650  * @param out the reference to the caller, i.e. left side of \c <<.
651  * @param lpi the constant reference to the linear program whose
652  * representation we want.
653  * @return The address of the caller.
654  */
655  template < typename T >
656  friend std::ostream&
657  operator<<(std::ostream& out,
658  const LpInterface< T >& lpi); // calls lpi.toString(),
659  // friend is useless but good
660  // for documentation purpose
661 
662  /**
663  * @brief Insert a new column, i.e. a new variable.
664  * @return A copy of the variable.
665  */
666  LpCol addCol();
667 
668  /**
669  * @brief Insert new columns, i.e. new variables.
670  * @param cols the constant reference to the number of variables we want.
671  * @return The copy of the vector of all variables of the problem.
672  */
673  std::vector< LpCol > addCols(const unsigned int& cols);
674 
675  /**
676  * @brief Add rows to the linear program according to a given expression
677  * (
678  * which must be at least an inequality ).
679  * @param expr the constant reference to the expression to convert to
680  * rows.
681  */
682  void addRow(const LpExpr& expr);
683 
684  /**
685  * @brief Add rows to the linear program according to a given expression
686  * (
687  * which must be at least an inequality ).
688  * @param expr the temporary expression to move to rows.
689  */
690  void addRow(LpExpr&& expr);
691 
692  /**
693  * @brief Add positivity constraints for all variables
694  */
695  void addPositivity();
696 
697  /**
698  * @brief Add sum of variables is 1 constraints
699  */
700  void addSumIsOne();
701 
702  /**
703  * @brief Add positivity constraints and sum of variables is 1 (
704  * probability
705  * constraints )
706  */
707  void addProba();
708 
709  /**
710  * @brief Solve the linear program (H-representation of the polytope) by
711  *enumeration (of the polytope vertices) using lexicographic reverse
712  *search
713  *(lrs).
714  *
715  * Only works with bounded polyhedron (polytopes) and not unbounded ones
716  *(i.e.
717  *defined by vertices and rays).
718  *
719  * @return The V-representation (vertices) of the polytope as a vector of
720  *vectors (vector of vertices).
721  */
722  std::vector< std::vector< GUM_SCALAR > > solve();
723 
724  /**
725  * @brief Get the variables of the LP.
726  * @return A copy of the variables as a vector of variables.
727  */
728  std::vector< LpCol > getCols() const;
729 
730  /**
731  * @brief Get the string representation of a calling linear program.
732  * @return The string representation of the calling linear program.
733  */
734  std::string toString() const;
735 
736  /**
737  * @brief Reset the rows (inequalities) and columns (variables) of the LP
738  * as
739  * if it was created.
740  */
741  void clear();
742  /**
743  * @brief Reset the rows (inequalities) of the LP but not the columns
744  * (variables are kept).
745  */
746  void clearRows();
747 
748  protected:
749  private:
750  /** @brief Rows of the problem. */
751  std::vector< LpRow* > rows__;
752  /** @brief %Variables of the problem. */
753  std::vector< LpCol > cols__;
754 
755  /** @brief \c true if addPositivity() has been called, \c false
756  * otherwise. */
757  bool positivity__;
758  /** @brief \c true if addSumIsOne() has been called, \c false otherwise.
759  */
760  bool sumIsOne__;
761 
762  }; // end of class LpInterface
763 
764  /**
765  * @brief Swap the addresses of two pointers to hashTables.
766  *
767  * Used by move operations as the temporary will take care of the delete
768  *operations.
769  * @warning DO NOT call this directly ( one of the object owning a pointer
770  *must
771  *be a temporary, i.e. an "rvalue reference" ).
772  * @param a the address of the first pointer.
773  * @param b the address of the second pointer.
774  */
775  void swap(HashTable< LpCol, double >*& a, HashTable< LpCol, double >*& b);
776 
777  /// @name Non-members operators +
778  /// @{
779 
780  /**
781  * @brief Overload of operator \c + between anything ( a scalar, a
782  * variable or an expression ) and anything except a temporary expression.
783  *
784  * Implements both the copy operator \c + and move operator \c + because
785  * operator \c + is implemented on top of operators \c +=. Because of
786  * template type deduction both \c lhs and \c rhs are "universal
787  * references", i.e. either an lvalue or an rvalue reference. Therefor
788  * std::forward must be used to forward the type of \c lhs and \c rhs.
789  *
790  * @param lhs the rvalue reference to the temporary expression on the
791  * right hand side of the operator.
792  * @param rhs the universal reference to either a scalar, a variable or a
793  * lvalue expression on the right hand side of the operator.
794  * @tparam T2 A scalar type ( integer or float ( any precision ) ) or a \c
795  * LpCol or a \c LpExpr.
796  * @return An expression which yields the result of \c lhs \c + \c rhs.
797  */
798  template < typename T2 >
799  LpExpr operator+(LpExpr&& lhs, const T2& rhs);
800  template < typename T2 >
801  LpExpr operator+(LpExpr& lhs, const T2& rhs);
802 
803  /**
804  * @brief Overload of operator \c + between anything ( a scalar, a
805  * variable or an expression ) and a temporary expression.
806  *
807  * This overload is used because only one side of the operator profit from
808  * move operation; the one with a temporary expression. If the expression
809  * if on the right hand side, we always add it first to profit from move
810  * operation. Otherwise another overload is used.
811  *
812  * Implements both the copy operator \c + and move operator \c + because
813  * operator \c + is implemented on top of operators \c +=. Because of
814  * template type deduction \c lhs is a "universal reference", i.e. either
815  * an lvalue or an rvalue reference. To force rvalue reference with
816  * template deduction one should use const : const T&& lhs : lhs is an
817  * rvalue reference and WILL be modified ( not intuitive const ).
818  * Therefor std::forward must be used to forward the type of \c lhs. \c
819  * rhs is an rvalue reference and std::move must be used to forward it's
820  * type.
821  *
822  * @param lhs the universal reference to either a scalar, a variable or an
823  * expression on the left hand side of the operator.
824  * @param rhs the rvalue reference to the temporary expression on the
825  * right hand side of the operator.
826  * @tparam T1 A scalar type ( integer or float ( any precision ) ) or a \c
827  * LpCol or a \c LpExpr.
828  * @warning T1 can not be LpExpr (to avoid ambiguity with previous
829  * functions)
830  * @return An expression which yields the result of \c lhs \c + \c rhs.
831  */
832  template < typename T1, forbidden_type< T1, LpExpr > = 0 >
833  LpExpr operator+(const T1& lhs, LpExpr&& rhs);
834  template < typename T1, forbidden_type< T1, LpExpr > = 0 >
835  LpExpr operator+(const T1& lhs, LpExpr& rhs);
836 
837  /**
838  * operator+ between LpCol lhs and not LpExpr rhs
839  */
840  template < typename T2, forbidden_type< T2, LpExpr > = 0 >
841  LpExpr operator+(const LpCol& lhs, const T2& rhs);
842 
843  /**
844  * operator+ between neither LpExpr nor LpCol lhs and LpCol rhs
845  */
846  template < typename T1,
847  forbidden_type< T1, LpExpr > = 0,
848  forbidden_type< T1, LpCol > = 0 >
849  LpExpr operator+(const T1& lhs, const LpCol& rhs);
850  /// @}
851 
852  /// @name Non-members operators -
853  /// @{
854  /**
855  * @brief Overload of operator \c - between anything ( a scalar, a
856  * variable or an expression ) and anything except a temporary expression.
857  *
858  * Implements both the copy operator \c - and move operator \c - because
859  * operator \c - is implemented on top of operators \c -=. Because of
860  * template type deduction both \c lhs and \c rhs are "universal
861  * references", i.e. either an lvalue or an rvalue reference. Therefor
862  * std::forward must be used to forward the type of \c lhs and \c rhs.
863  *
864  * @param lhs the rvalue reference to the temporary expression on the
865  * right hand side of the operator.
866  * @param rhs the universal reference to either a scalar, a variable or a
867  * lvalue expression on the right hand side of the operator.
868  * @tparam T2 A scalar type ( integer or float ( any precision ) ) or a \c
869  * LpCol or a \c LpExpr.
870  * @return An expression which yields the result of \c lhs \c -\c rhs.
871  */
872  template < typename T2 >
873  LpExpr operator-(LpExpr&& lhs, const T2& rhs);
874  template < typename T2 >
875  LpExpr operator-(LpExpr& lhs, const T2& rhs);
876 
877  /**
878  * @brief Overload of operator \c - between anything ( a scalar, a
879  * variable or an expression ) and a temporary expression.
880  *
881  * This overload is used because only one side of the operator profit from
882  * move operation; the one with a temporary expression. If the expression
883  * if on the right hand side, we always add it first to profit from move
884  * operation. Otherwise another overload is used.
885  *
886  * Implements both the copy operator \c - and move operator \c - because
887  * operator \c - is implemented on top of operators \c -=. Because of
888  * template type deduction \c lhs is a "universal reference", i.e. either
889  * an lvalue or an rvalue reference. To force rvalue reference with
890  * template deduction one should use const : const T&& lhs : lhs is an
891  * rvalue reference and WILL be modified ( not intuitive const ).
892  * Therefor std::forward must be used to forward the type of \c lhs. \c
893  * rhs is an rvalue reference and std::move must be used to forward it's
894  * type.
895  *
896  * @param lhs the universal reference to either a scalar, a variable or an
897  * expression on the left hand side of the operator.
898  * @param rhs the rvalue reference to the temporary expression on the
899  * right hand side of the operator.
900  * @tparam T1 A scalar type ( integer or float ( any precision ) ) or a \c
901  * LpCol or a \c LpExpr.
902  * @warning T1 can not be LpExpr (to avoid ambiguity with previous
903  * functions)
904  * @return An expression which yields the result of \c lhs \c - \c rhs.
905  */
906  template < typename T1, forbidden_type< T1, LpExpr > = 0 >
907  LpExpr operator-(const T1& lhs, LpExpr&& rhs);
908  template < typename T1, forbidden_type< T1, LpExpr > = 0 >
909  LpExpr operator-(const T1& lhs, LpExpr& rhs);
910 
911  /**
912  * operator- between LpCol lhs and not LpExpr rhs
913  *
914  * @param lhs the universal reference to either a scalar, a variable or an
915  * expression on the left hand side of the operator.
916  * @param rhs the rvalue reference to the temporary expression on the
917  * right hand side of the operator.
918  * @tparam T2 A scalar type ( integer or float ( any precision ) ) or a \c
919  * LpCol or a \c LpExpr.
920  */
921  template < typename T2, forbidden_type< T2, LpExpr > = 0 >
922  LpExpr operator-(const LpCol& lhs, const T2& rhs);
923 
924  /**
925  * operator- between neither LpExpr nor LpCol lhs and LpCol rhs
926  *
927  * @param lhs the universal reference to either a scalar, a variable or an
928  * expression on the left hand side of the operator.
929  * @param rhs the rvalue reference to the temporary expression on the
930  * right hand side of the operator.
931  * @tparam T1 A scalar type ( integer or float ( any precision ) ) or a \c
932  * LpCol or a \c LpExpr.
933  */
934  template < typename T1,
935  forbidden_type< T1, LpExpr > = 0,
936  forbidden_type< T1, LpCol > = 0 >
937  LpExpr operator-(const T1& lhs, const LpCol& rhs);
938  /// @}
939 
940  /// @name Non-members operators *
941  /// @{
942 
943  /**
944  * @brief Overload of operator \c * between a scalar and a variable.
945  *
946  * @param lhs the constant reference to the scalar on the left hand side
947  * of the operator.
948  * @param rhs the constant reference to the variable on the right hand
949  * side of the operator.
950  * @tparam SCALAR A scalar type ( integer or float ( any precision ) ) or
951  * a \c LpCol or a \c LpExpr.
952  * @return An expression which yields the result of \c lhs \c * \c rhs.
953  */
954  template < typename SCALAR >
955  LpExpr operator*(const SCALAR& lhs, const LpCol& rhs);
956 
957  /**
958  * @brief Overload of operator \c * between a variable and a scalar.
959  *
960  * @param lhs the constant reference to the variable on the left hand side
961  * of the operator.
962  * @param rhs the constant reference to the scalar on the right hand side
963  * of the operator.
964  * @tparam SCALAR A scalar type ( integer or float ( any precision ) ) or
965  * a \c LpCol or a \c LpExpr.
966  * @return An expression which yields the result of \c lhs \c * \c rhs.
967  */
968  template < typename SCALAR >
969  LpExpr operator*(const LpCol& lhs, const SCALAR& rhs);
970 
971  /// @}
972 
973  /// @name Non-members operators <=
974  /// @{
975 
976  /**
977  * @brief Overload of operator \c <= between anything and anything.
978  *
979  * Implements both the copy operator \c <= and move operator \c <=.
980  * Because of template type deduction both \c lhs and \c rhs are
981  * "universal references", i.e. either an lvalue or an rvalue reference.
982  * Therefor std::forward must be used to forward the type of \c lhs and \c
983  * rhs.
984  *
985  * @param lhs the universal reference to either a ( temporary ) scalar, a
986  * ( temporary ) variable or a ( temporary ) expression on the left hand
987  * side of the operator.
988  * @param rhs the universal reference to either a ( temporary ) scalar, a
989  * ( temporary ) variable or a ( temporary ) expression on the right hand
990  * side of the operator.
991  * @tparam T1 A scalar type ( integer or float ( any precision ) ) or a \c
992  * LpCol or a \c LpExpr.
993  * @tparam T2 A scalar type ( integer or float ( any precision ) ) or a \c
994  * LpCol or a \c LpExpr.
995  * @return An expression which yields the result of \c lhs \c <= \c rhs.
996  */
997  template < typename T2 >
998  LpExpr operator<=(const LpExpr& lhs, T2&& rhs);
999  template < typename T2 >
1000  LpExpr operator<=(const LpCol& lhs, T2&& rhs);
1001  template < typename T1,
1002  forbidden_type< T1, LpExpr& > = 0,
1003  forbidden_type< T1, LpCol& > = 0 >
1004  LpExpr operator<=(T1&& lhs, const LpExpr& rhs);
1005  template < typename T1,
1006  forbidden_type< T1, LpExpr& > = 0,
1007  forbidden_type< T1, LpCol& > = 0 >
1008  LpExpr operator<=(T1&& lhs, const LpCol& rhs);
1009 
1010  template < typename T2 >
1011  LpExpr operator<=(LpExpr&& lhs, T2&& rhs);
1012  template < typename T2 >
1013  LpExpr operator<=(LpCol&& lhs, T2&& rhs);
1014  template < typename T1,
1015  forbidden_type< T1, LpExpr > = 0,
1016  forbidden_type< T1, LpCol > = 0 >
1017  LpExpr operator<=(T1&& lhs, LpExpr&& rhs);
1018  template < typename T1,
1019  forbidden_type< T1, LpExpr > = 0,
1020  forbidden_type< T1, LpCol > = 0 >
1021  LpExpr operator<=(T1&& lhs, LpCol&& rhs);
1022 
1023  /// @}
1024 
1025  } // end of namespace lp
1026 
1027  } // namespace credal
1028 
1029 } // end of namespace gum
1030 
1031 #include <agrum/CN/polytope/LpInterface_tpl.h>
1032 
1033 #ifndef GUM_NO_INLINE
1034 # include <agrum/CN/polytope/LpInterface_inl.h>
1035 #endif /* GUM_NO_INLINE */
1036 
1037 #endif