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