From f3013a4daf5783c9b5145f135cb4a7bf7a258c51 Mon Sep 17 00:00:00 2001
From: andreadelprete <andre.delprete@gmail.com>
Date: Tue, 3 Nov 2015 11:59:34 +0100
Subject: [PATCH] Add binary files describing some LP problems in folder
 test_data. Add test LP solver using binary files.

---
 .../solver_LP_abstract.hh                     |   6 +--
 include/robust-equilibrium-lib/util.hh        |  12 +++--
 src/solver_LP_abstract.cpp                    |  10 ++--
 src/static_equilibrium.cpp                    |  23 ++++++++
 src/util.cpp                                  |  12 +++++
 test/test_LP_solvers.cpp                      |  50 +++++++++++++++++-
 test/test_static_equilibrium.cpp              |   6 +--
 ...LP_findExtremumOverLine20151103_112611.dat | Bin 0 -> 1248 bytes
 ...tremumOverLine20151103_112611_solution.dat | Bin 0 -> 64 bytes
 ...LP_findExtremumOverLine20151103_115627.dat | Bin 0 -> 1248 bytes
 ...tremumOverLine20151103_115627_solution.dat | Bin 0 -> 64 bytes
 ...LP_findExtremumOverLine20151103_112610.dat | Bin 0 -> 1336 bytes
 ...tremumOverLine20151103_112610_solution.dat | Bin 0 -> 152 bytes
 ...LP_findExtremumOverLine20151103_112611.dat | Bin 0 -> 1336 bytes
 ...tremumOverLine20151103_112611_solution.dat | Bin 0 -> 152 bytes
 15 files changed, 103 insertions(+), 16 deletions(-)
 create mode 100644 test_data/DLP_findExtremumOverLine20151103_112611.dat
 create mode 100644 test_data/DLP_findExtremumOverLine20151103_112611_solution.dat
 create mode 100644 test_data/DLP_findExtremumOverLine20151103_115627.dat
 create mode 100644 test_data/DLP_findExtremumOverLine20151103_115627_solution.dat
 create mode 100644 test_data/LP_findExtremumOverLine20151103_112610.dat
 create mode 100644 test_data/LP_findExtremumOverLine20151103_112610_solution.dat
 create mode 100644 test_data/LP_findExtremumOverLine20151103_112611.dat
 create mode 100644 test_data/LP_findExtremumOverLine20151103_112611_solution.dat

diff --git a/include/robust-equilibrium-lib/solver_LP_abstract.hh b/include/robust-equilibrium-lib/solver_LP_abstract.hh
index 148fdc5..a8555e7 100644
--- a/include/robust-equilibrium-lib/solver_LP_abstract.hh
+++ b/include/robust-equilibrium-lib/solver_LP_abstract.hh
@@ -54,7 +54,7 @@ public:
    * @param sol Output solution of the LP.
    * @return A flag describing the final status of the solver.
    */
-  virtual LP_status solve(const char* filename, Ref_vectorX sol);
+  virtual LP_status solve(const std::string& filename, Ref_vectorX sol);
 
   /**
    * @brief Write the specified Linear Program to binary file.
@@ -70,7 +70,7 @@ public:
    * @param Aub
    * @return True if the operation succeeded, false otherwise.
    */
-  virtual bool writeLpToFile(const char* filename,
+  virtual bool writeLpToFile(const std::string& filename,
                              Cref_vectorX c, Cref_vectorX lb, Cref_vectorX ub,
                              Cref_matrixXX A, Cref_vectorX Alb, Cref_vectorX Aub);
 
@@ -89,7 +89,7 @@ public:
    * @param Aub
    * @return True if the operation succeeded, false otherwise.
    */
-  virtual bool readLpFromFile(const char* filename,
+  virtual bool readLpFromFile(const std::string& filename,
                               VectorX &c, VectorX &lb, VectorX &ub,
                               MatrixXX &A, VectorX &Alb, VectorX &Aub);
 
diff --git a/include/robust-equilibrium-lib/util.hh b/include/robust-equilibrium-lib/util.hh
index 5c22c80..759fff9 100644
--- a/include/robust-equilibrium-lib/util.hh
+++ b/include/robust-equilibrium-lib/util.hh
@@ -66,29 +66,31 @@ namespace robust_equilibrium
    * Write the specified matrix to a binary file with the specified name.
    */
   template<class Matrix>
-  void writeMatrixToFile(const char* filename, const Matrix& matrix)
+  bool writeMatrixToFile(const std::string &filename, const Matrix& matrix)
   {
-    std::ofstream out(filename, std::ios::out | std::ios::binary | std::ios::trunc);
+    std::ofstream out(filename.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
     typename Matrix::Index rows=matrix.rows(), cols=matrix.cols();
     out.write((char*) (&rows), sizeof(typename Matrix::Index));
     out.write((char*) (&cols), sizeof(typename Matrix::Index));
     out.write((char*) matrix.data(), rows*cols*sizeof(typename Matrix::Scalar) );
     out.close();
+    return true;
   }
 
   /**
    * Read a matrix from the specified input binary file.
    */
   template<class Matrix>
-  void readMatrixFromFile(const char* filename, Matrix& matrix)
+  bool readMatrixFromFile(const std::string &filename, Matrix& matrix)
   {
-    std::ifstream in(filename, std::ios::in | std::ios::binary);
+    std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
     typename Matrix::Index rows=0, cols=0;
     in.read((char*) (&rows),sizeof(typename Matrix::Index));
     in.read((char*) (&cols),sizeof(typename Matrix::Index));
     matrix.resize(rows, cols);
     in.read( (char *) matrix.data() , rows*cols*sizeof(typename Matrix::Scalar) );
     in.close();
+    return true;
   }
 
   /**
@@ -116,6 +118,8 @@ namespace robust_equilibrium
   bool generate_rectangle_contacts(double lx, double ly, Cref_vector3 pos, Cref_vector3 rpy,
                                    Ref_matrix43 p, Ref_matrix43 N);
 
+  std::string getDateAndTimeAsString();
+
 } //namespace robust_equilibrium
 
 #endif //_ROBUST_EQUILIBRIUM_LIB_UTIL_HH
diff --git a/src/solver_LP_abstract.cpp b/src/solver_LP_abstract.cpp
index 6bfbadd..2906c9b 100644
--- a/src/solver_LP_abstract.cpp
+++ b/src/solver_LP_abstract.cpp
@@ -32,7 +32,7 @@ Solver_LP_abstract* Solver_LP_abstract::getNewSolver(SolverLP solverType)
   return NULL;
 }
 
-bool Solver_LP_abstract::writeLpToFile(const char* filename,
+bool Solver_LP_abstract::writeLpToFile(const std::string& filename,
                                        Cref_vectorX c, Cref_vectorX lb, Cref_vectorX ub,
                                        Cref_matrixXX A, Cref_vectorX Alb, Cref_vectorX Aub)
 {
@@ -43,7 +43,7 @@ bool Solver_LP_abstract::writeLpToFile(const char* filename,
   assert(Alb.size()==m);
   assert(Aub.size()==m);
 
-  std::ofstream out(filename, std::ios::out | std::ios::binary | std::ios::trunc);
+  std::ofstream out(filename.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
   out.write((char*) (&n), sizeof(typename MatrixXX::Index));
   out.write((char*) (&m), sizeof(typename MatrixXX::Index));
   out.write((char*) c.data(), n*sizeof(typename MatrixXX::Scalar) );
@@ -56,11 +56,11 @@ bool Solver_LP_abstract::writeLpToFile(const char* filename,
   return true;
 }
 
-bool Solver_LP_abstract::readLpFromFile(const char* filename,
+bool Solver_LP_abstract::readLpFromFile(const std::string& filename,
                                         VectorX &c, VectorX &lb, VectorX &ub,
                                         MatrixXX &A, VectorX &Alb, VectorX &Aub)
 {
-  std::ifstream in(filename, std::ios::in | std::ios::binary);
+  std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
   typename MatrixXX::Index n=0, m=0;
   in.read((char*) (&n),sizeof(typename MatrixXX::Index));
   in.read((char*) (&m),sizeof(typename MatrixXX::Index));
@@ -80,7 +80,7 @@ bool Solver_LP_abstract::readLpFromFile(const char* filename,
   return true;
 }
 
-LP_status Solver_LP_abstract::solve(const char* filename, Ref_vectorX sol)
+LP_status Solver_LP_abstract::solve(const std::string& filename, Ref_vectorX sol)
 {
   VectorX c, lb, ub, Alb, Aub;
   MatrixXX A;
diff --git a/src/static_equilibrium.cpp b/src/static_equilibrium.cpp
index 27116eb..e856093 100644
--- a/src/static_equilibrium.cpp
+++ b/src/static_equilibrium.cpp
@@ -8,6 +8,7 @@
 #include <robust-equilibrium-lib/stop-watch.hh>
 #include <iostream>
 #include <vector>
+#include <ctime>
 
 using namespace std;
 
@@ -303,6 +304,18 @@ bool StaticEquilibrium::findExtremumOverLine(Cref_vector2 a, Cref_vector2 a0, do
     if(lpStatus_primal==LP_STATUS_OPTIMAL)
     {
       com = a0 + a*b_p(m);
+
+#define WRITE_LPS_TO_FILE
+#ifdef WRITE_LPS_TO_FILE
+      string date_time = getDateAndTimeAsString();
+      string filename = "LP_findExtremumOverLine"+date_time+".dat";
+      if(!m_solver->writeLpToFile(filename.c_str(), c, lb, ub, A, Alb, Aub))
+        SEND_ERROR_MSG("Error while writing LP to file "+filename);
+      filename = "LP_findExtremumOverLine"+date_time+"_solution.dat";
+      if(!writeMatrixToFile(filename.c_str(), b_p))
+        SEND_ERROR_MSG("Error while writing LP solution to file "+filename);
+#endif
+
       return true;
     }
 
@@ -342,6 +355,16 @@ bool StaticEquilibrium::findExtremumOverLine(Cref_vector2 a, Cref_vector2 a0, do
       double p = m_solver->getObjectiveValue();
       com = a0 + a*p;
 
+#ifdef WRITE_LPS_TO_FILE
+      string date_time = getDateAndTimeAsString();
+      string filename = "DLP_findExtremumOverLine"+date_time+".dat";
+      if(!m_solver->writeLpToFile(filename.c_str(), c, lb, ub, A, Alb, Aub))
+        SEND_ERROR_MSG("Error while writing LP to file "+filename);
+      filename = "DLP_findExtremumOverLine"+date_time+"_solution.dat";
+      if(!writeMatrixToFile(filename.c_str(), v))
+        SEND_ERROR_MSG("Error while writing LP solution to file "+filename);
+#endif
+
       // since QP oases cannot detect unboundedness we check here whether the objective value is a large negative value
       if(m_solver_type==SOLVER_LP_QPOASES && p<-1e7)
       {
diff --git a/src/util.cpp b/src/util.cpp
index fa1cede..7ffb2ae 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -7,6 +7,7 @@
 #define _ROBUST_EQUILIBRIUM_LIB_CONFIG_HH
 
 #include <robust-equilibrium-lib/util.hh>
+#include <ctime>
 
 namespace robust_equilibrium
 {
@@ -130,6 +131,17 @@ Rotation crossMatrix(Cref_vector3 x)
     return res;
 }
 
+std::string getDateAndTimeAsString()
+{
+  time_t rawtime;
+  struct tm * timeinfo;
+  char buffer[80];
+  time (&rawtime);
+  timeinfo = localtime(&rawtime);
+  strftime(buffer,80,"%Y%m%d_%I%M%S",timeinfo);
+  return std::string(buffer);
+}
+
 } //namespace robust_equilibrium
 
 #endif //_ROBUST_EQUILIBRIUM_LIB_CONFIG_HH
diff --git a/test/test_LP_solvers.cpp b/test/test_LP_solvers.cpp
index eee930d..27faf5d 100644
--- a/test/test_LP_solvers.cpp
+++ b/test/test_LP_solvers.cpp
@@ -22,6 +22,8 @@ using namespace std;
 using namespace robust_equilibrium;
 USING_NAMESPACE_QPOASES
 
+#define EPS 1e-6
+
 #ifdef CLP_FOUND
 /** Example addRows.cpp */
 void test_addRows()
@@ -428,12 +430,58 @@ int main()
     cout<<"Check constraint matrix A: "<<A.isApprox(A2)<<endl;
     cout<<"Check constraint lower bound vector Alb: "<<Alb.isApprox(Alb2)<<endl;
     cout<<"Check constraint upper bound vector Aub: "<<Aub.isApprox(Aub2)<<endl;
+  }
+
+  {
+    cout<<"\nTEST QP OASES ON SOME LP PROBLEMS\n";
+    string file_path = "../test_data/";
+    Solver_LP_abstract *solverOases = Solver_LP_abstract::getNewSolver(SOLVER_LP_QPOASES);
+    const int PROBLEM_NUMBER = 4;
+    string problem_filenames[PROBLEM_NUMBER] = {"DLP_findExtremumOverLine20151103_112611",
+                                                "DLP_findExtremumOverLine20151103_115627",
+                                                "LP_findExtremumOverLine20151103_112610",
+                                                "LP_findExtremumOverLine20151103_112611"};
+    VectorX c, lb, ub, Alb, Aub, realSol, sol;
+    MatrixXX A;
+    for(int i=0; i<PROBLEM_NUMBER; i++)
+    {
+      string &problem_filename = problem_filenames[i];
+      if(!solverOases->readLpFromFile(file_path+problem_filename+".dat", c, lb, ub, A, Alb, Aub))
+      {
+        SEND_ERROR_MSG("Error while reading LP from file "+problem_filename);
+        return -1;
+      }
+      string solution_filename = problem_filename+"_solution";
+      if(!readMatrixFromFile(file_path+solution_filename+".dat", realSol))
+      {
+        SEND_ERROR_MSG("Error while reading LP solution from file "+solution_filename);
+        return -1;
+      }
+      sol.resize(c.size());
+      solverOases->solve(c, lb, ub, A, Alb, Aub, sol);
+      if(sol.isApprox(realSol, EPS))
+      {
+        cout<<"[INFO] Solution of problem "<<problem_filename<<" is equal to the expected value!\n";
+      }
+      else
+      {
+        if(fabs(c.dot(sol)-c.dot(realSol))<EPS)
+          cout<<"[WARNING] Solution of problem "<<problem_filename<<" is different from expected but it has the same cost\n";
+        else
+        {
+          cout<<"[ERROR] Solution of problem "<<problem_filename<<" is different from the expected value:\n";
+          cout<<"\tSolution found    "<<sol.transpose()<<endl;
+          cout<<"\tExpected solution "<<realSol.transpose()<<endl;
+          cout<<"\tCost found    "<<(c.dot(sol))<<endl;
+          cout<<"\tCost expected "<<(c.dot(realSol))<<endl;
+        }
+      }
+    }
 
     return 0;
   }
 
 
-
 #ifdef CLP_FOUND
   test_addRows();
   test_small_LP();
diff --git a/test/test_static_equilibrium.cpp b/test/test_static_equilibrium.cpp
index 2834c56..17b9368 100644
--- a/test/test_static_equilibrium.cpp
+++ b/test/test_static_equilibrium.cpp
@@ -260,8 +260,8 @@ int main()
   /************************************** USER PARAMETERS *******************************/
   double mass = 70.0;
   double mu = 0.3;  // friction coefficient
-  unsigned int generatorsPerContact = 8;
-  unsigned int N_CONTACTS = 2;
+  unsigned int generatorsPerContact = 4;
+  unsigned int N_CONTACTS = 1;
   double MIN_FEET_DISTANCE = 0.3;
   double LX = 0.5*0.2172;        // half contact surface size in x direction
   double LY = 0.5*0.138;         // half contact surface size in y direction
@@ -272,7 +272,7 @@ int main()
   RPY_UPPER_BOUNDS << +0*gamma, +0*gamma, +M_PI;
   double X_MARG = 0.07;
   double Y_MARG = 0.07;
-  const int GRID_SIZE = 15;
+  const int GRID_SIZE = 5;
   /************************************ END USER PARAMETERS *****************************/
 
   cout<<"Number of contacts: "<<N_CONTACTS<<endl;
diff --git a/test_data/DLP_findExtremumOverLine20151103_112611.dat b/test_data/DLP_findExtremumOverLine20151103_112611.dat
new file mode 100644
index 0000000000000000000000000000000000000000..b22aa57c927127ef59bb14e8f00c5d1fb545e64d
GIT binary patch
literal 1248
zcmZQ$fB-=#y-_!1)4F8lz3JWRaeLL6Z4(OE9XO@J4^*h!c^CQV%l;M1r|)0BTGyec
zplj~SnOAIp+7#j!FdZV1c7m!Wh6cOriqp}g7s;3Gw;%EFZ(jCp|MkD26C4*U+V67Z
zV_T`lYWqV^W4Bj&Pq2rn>zDozE$>-k15@9(?E#Ny##(zVB`(g*XAaqS<|^dfTr$xf
zqOQdTs&79`{oY%xuV%#@ws(V?e-L8+ewey2%@>^ObNlwd)K7$(uk^r0?BT;D`@10K
z?*}^`NWk0$Q$OqQ#QQh<j_$v>A!UQb%jNdRbA_zRH}>FkKcj9(L5IZV{eCyoE<gTr
z&^~?6wP4#<)Ar+X|A{R=72TUA+h2y7e-dIoPWLlF&7aDA>5Z)7iv4L2^X+lD-`#Bb
z**8~@?PuAzXwd=B3-;MpV!mze-i*`z(L$4b)-Bt*e`3358MpT}`^%5S`ptjO#OeM6
zc1{8>J~!E;nUB-`QBd>WZTUX;^@Jn#7a->2bbrr@Y>(c3%l8+Bme{V?c)?zY;ZsdA
z#}=IKzxn!9$Vu-N_W!k|1wU`PW^dznAa$R5FV6HMkkRm`UG$JWn)x{0e+O#*slT%>
z?@Bmo?+7s;o_=8Q0Hckf&$Xp_B^~&-c8_f0)rtd9@dlXuz|tQ;?go_$#N=;UsRKIU
G!+roTDcv#v

literal 0
HcmV?d00001

diff --git a/test_data/DLP_findExtremumOverLine20151103_112611_solution.dat b/test_data/DLP_findExtremumOverLine20151103_112611_solution.dat
new file mode 100644
index 0000000000000000000000000000000000000000..de3853d919e0105c791f2fe9e829c8b57c4cef4a
GIT binary patch
literal 64
zcmZQ$fB;4)&9KGc)b~v9{R|C@rYsa>-Ounro6TmSqCG={cvFd@!hVKRP0GT5Q|uwi
HKiL2P%VrRl

literal 0
HcmV?d00001

diff --git a/test_data/DLP_findExtremumOverLine20151103_115627.dat b/test_data/DLP_findExtremumOverLine20151103_115627.dat
new file mode 100644
index 0000000000000000000000000000000000000000..15d24c756d1aad60ffaadcf9f299578f5be0f390
GIT binary patch
literal 1248
zcmZQ$fB-=#eOotW)4F8ly%W0C<MygC+bZO<J8(*cA9zwxqNkjoaNtJgR@-<zDF=wU
z%Qir53h@h=4v|PZLDdsOgI#vT>1fi6<V*J3k9hbuFMGE?BWzk*zW=HH*C!<Gx)*cA
zp7CMvn!@}Q_Aqt*(jTJbJxgq0>L-@`v0GApbpN`dUyQ3vPTE(gCP^GUv~oX0U5gD=
z-+q|-U6Yc&-<W>@Zax#l{QWR>VVW;E*XQ=_fvJa?&k)!9RE=xDeI>+vd$8ky1k7D9
z_2yU9ZhUszyuY1AhV_8mar=DMj+|#tR^xQPpyIQMyYv?Ck9)S&r(5id{rxESNB3FU
zak`&DZL@=$rG-73`8eG#05yMuQq$fqX@~4@L(IqNes|_mTooBh_KSXea$4u>^!?9v
z2}PgZUjsAW9zFb*?o&UuZc4&_FY7B0qbBv*AAXY5KJTeBPWKmcvl=}LU1TqUYCbG{
z_M?aY1gQBh{ztYPj$FV0G{k(I?w8Lsohy9o=>7or2NR^5mhabne{=0F(;l4e_voG-
z>hbQt{xkm{o!r^ous`h9+nLINOK`gXQ4q7tFP$Cx{h{V-LCnYLewg`T&liU;DcA}#
zAMSowI)c$g(dXLIypj%lTf0X#@oL2ZsCWZReqiYj`+@d@$^~NbH?7nGo$z5l0EmU!
AhyVZp

literal 0
HcmV?d00001

diff --git a/test_data/DLP_findExtremumOverLine20151103_115627_solution.dat b/test_data/DLP_findExtremumOverLine20151103_115627_solution.dat
new file mode 100644
index 0000000000000000000000000000000000000000..d1684bd0081edc83e4e41ea4ea7caf55e05c95b0
GIT binary patch
literal 64
zcmZQ$fB;4)&Cqap?J-01{R}UX$~?IQ_A}HhRM+|fqzf`{mzCJ<XV9rx^M)nO9<1CV
GcrO6oa}m@4

literal 0
HcmV?d00001

diff --git a/test_data/LP_findExtremumOverLine20151103_112610.dat b/test_data/LP_findExtremumOverLine20151103_112610.dat
new file mode 100644
index 0000000000000000000000000000000000000000..0071f421913be82d09807d6360b1671f39966b2b
GIT binary patch
literal 1336
zcmWe+fB-fqJvgWj`=Rb=7*IOv#{r=I3h@h=oCX064vH&IN0VM8U$XC){tzwi*<u6b
z!@`S!zVan-`@=L}aIVko+k<L9_2t2V03@~_@$he6_HO?`(J*&h{~J2NanYjvecK-J
zh-R#{-+Qa|)vTDq_7kD}S%)Xyzu9+mKcj9(L5IZV{U^5gRCI5eY|jAYyPHiv`{wGg
z{n0{`ebz18y8nQklfaA5P4-bxe$R<)kKTRD_uqVdD&(a13VVT!hCl71hwSe_`KL|a
zrb-009&owxv8_~NwY`=S7w6_PhwR;;e5D62Vh<lK*?)0E$_9&<%kBMcrd@vg=b-&%
zD1R#Rr8lyQEB3Q&T(szb=LP$T?Ve@a-q-A5{C8Wv&wV}Nh<#CLiS3Gw7wrFQOACJ9
zbPdiw^>^0gT?t3+xm&Z2%h!ZC9C{kNz0!MveP^yh-pwTw?GHlu`@10g{l{~Ktjag`
z*r(6A7Hs=!+WwOe{{A!w-#+_F%(u<mo9!<@66-hrJ##;lzyAV+Z?DAgsV13Yi@lBC
zfz*BKy)gcMM+hID4?e89xM$_dcYERwIEOWKyt7HyxT9((TXSFr|J<*)Y9$Y3G+cdg
Tmp91aL9)M&QqBPzQq=<hm$U4h

literal 0
HcmV?d00001

diff --git a/test_data/LP_findExtremumOverLine20151103_112610_solution.dat b/test_data/LP_findExtremumOverLine20151103_112610_solution.dat
new file mode 100644
index 0000000000000000000000000000000000000000..6a642a25eeddb2063090419fd83f76057f4558be
GIT binary patch
literal 152
zcmWe+fB;4)-DbsbUNttr;bhI6b09i1R2R&D(&&B(#D^$L*bP;VgDSAbE|IXi#rwPT
i-=Cfickgq_f#|)WbHV(jSGS0P_zz8PeK=CS+#UdzrzSxF

literal 0
HcmV?d00001

diff --git a/test_data/LP_findExtremumOverLine20151103_112611.dat b/test_data/LP_findExtremumOverLine20151103_112611.dat
new file mode 100644
index 0000000000000000000000000000000000000000..f2d649d86d6ad499229c13b0070b61069c28a23b
GIT binary patch
literal 1336
zcmWe+fB-fqJvgWj`=Rb=7*IOv#{r=I3h@h=oCX064vH&IN0VM8U$XC){tzwi*<u6b
z!@`S!zVan-`@=L}aIVko+k<L9_2t2V03@~_@$he6_HO?`(J*&h{~J2NanYjvecK-J
zh-R#{-+Qa|)vTDq_7kD}S%)Xyzu9+mKcj9(L5IZV{U^5gRCI5eY|jAYyPHiv`{wGg
z{n0{`ebz18y8nQklfaA5P4-bxe$R<)kKTRD_uqVdD&(a13VVT!hCl71hwSe_`I<_B
zT~+T354c?U*jB2s+FnbEi*xgtL-uY^zS091v4;<r?7z4nWrM}b<@SCz(=I>$bI|@W
zls}dE(i>UD75iB>E?RWJ^Md`vcF!_y?`!rj{<|&T=f0kB#J(uB#CFBT3-<rDr3F84
zx(4T;`aA3Lu7soZ{AW6?Y$U}T4n2+CUg<r-zB5-L@8*(;_6H&S{aq0L{^PkqR^=Oe
z?9=C53$}eVZU0FKe}5W;Z=Zc7=G*4(&GwfciS?WRp1B{&-+uwZw^w5LRFllH#oos6
zK<YmAUKoGBBZLpn2f;qRugtU`>`9lcdVli6eVYY+mXZb28V@i9vR2%EB7fkE>CUdT
S)507i6hB40(%oo7s(JvC4d_t-

literal 0
HcmV?d00001

diff --git a/test_data/LP_findExtremumOverLine20151103_112611_solution.dat b/test_data/LP_findExtremumOverLine20151103_112611_solution.dat
new file mode 100644
index 0000000000000000000000000000000000000000..1672cfe8e4f4ad7b5a9c70c02fccd6c2d3b073b5
GIT binary patch
literal 152
zcmWe+fB;4){YG*1vdgN$4xU#$mx5@OLw(CZbn>b*+d(u`8QD}(-Zi<d$$<_(PJ}6e
ZXp3{7WI^=3PnY>Y^poZ_*3Hoe?E%l0BMJZj

literal 0
HcmV?d00001

-- 
GitLab