From 9738521e69b9c935efbc3685bc1b042e47117511 Mon Sep 17 00:00:00 2001
From: Amaury Johnan <amjohnen@gmail.com>
Date: Wed, 11 Sep 2013 13:25:23 +0000
Subject: [PATCH] new algo before debug

---
 Mesh/meshGFaceRecombine.cpp | 563 +++++++++++++++++++++++++++++++++++-
 Mesh/meshGFaceRecombine.h   | 108 ++++++-
 2 files changed, 650 insertions(+), 21 deletions(-)

diff --git a/Mesh/meshGFaceRecombine.cpp b/Mesh/meshGFaceRecombine.cpp
index e105c89952..24bf038006 100644
--- a/Mesh/meshGFaceRecombine.cpp
+++ b/Mesh/meshGFaceRecombine.cpp
@@ -14,9 +14,10 @@
 #include "MQuadrangle.h"
 #include "PView.h"
 #include "meshGFace.h"
+#include <algorithm>
 
 #define REC2D_WAIT_SELECTED .01
-#define REC2D_WAIT_BEST_SEQ .1
+#define REC2D_WAIT_BEST_SEQ .03
 #define REC2D_WAIT_TM_1 .001
 #define REC2D_WAIT_TM_2 .001
 #define REC2D_WAIT_TM_3 .001
@@ -141,16 +142,16 @@ namespace {
     Msg::Info("%d",e);
   }
 
-  //void __wait(double dt = REC2D_WAIT_TM_3)
-  //{
-  //#ifdef REC2D_DRAW
-  //  Msg::Info(" ");
-  //  double time = Cpu();
-  //  while (Cpu()-time < dt)
-  //    FlGui::instance()->check();
-  //#endif
-  //}
-  //
+  void __wait(double dt = REC2D_WAIT_TM_3)
+  {
+  #ifdef REC2D_DRAW
+    Msg::Info(" ");
+    double time = Cpu();
+    while (Cpu()-time < dt)
+      FlGui::instance()->check();
+  #endif
+  }
+
   int otherParity(const int a)
   {
     if (a % 2)
@@ -179,6 +180,7 @@ Recombine2D::Recombine2D(GFace *gf, bool col)
     _strategy(0), _horizon(0), _qualCriterion(NoCrit),
     _checkIfNotAllQuad(1), _avoidIfNotAllQuad(1),
     _revertIfNotAllQuad(0), _oneActionHavePriority(1),
+    _noProblemIfObsolete(0),
     _weightEdgeBase(2),
     _weightEdgeQuad(1),
     _weightAngleTri(1),
@@ -500,6 +502,54 @@ void Recombine2D::recombineSameAsBlossom() // check if quality ok
     Msg::Info("Not ok :-(...");
 }
 
+void Recombine2D::recombineSameAsHeuristic()
+{
+  double globtime = Cpu();
+  _noProblemIfObsolete = true;
+  recombineHeuristic(_gf, .0, 1.1, elist, t2n);
+  _lastRunTime = Cpu() - globtime;
+  _data->_quad = _gf->quadrangles;
+  Recombine2D::drawStateOrigin();
+  
+  std::map<int, Rec2DElement*> n2rel;
+  std::map<MElement*,int>::iterator it = t2n.begin(); 
+  for (; it != t2n.end(); ++it) {
+    n2rel[it->second] = Rec2DData::getRElement(it->first);
+  }
+  
+  int blosQual = 0;
+  for (int i = 0; i < _cur->elist[0]; ++i) {
+    Rec2DElement *tri1 = n2rel[_cur->elist[3*i+1]];
+    Rec2DElement *tri2 = n2rel[_cur->elist[3*i+2]];
+    blosQual += _cur->elist[3*i+3];
+    Rec2DAction *ra = new Rec2DTwoTri2Quad(tri1, tri2);
+    int realRew = (int) ra->getRealReward();
+    if (realRew > ra->getRealReward()+.3) --realRew;
+    if (realRew < ra->getRealReward()-.3) ++realRew;
+    if ((int) ra->getRealReward()+_cur->elist[3*i+3] != 100)
+      Msg::Info("%d(%d-%g) - %d (%d, %d) => blosQual %d",
+                    (int) ra->getRealReward(),
+                    realRew,
+                    ra->getRealReward(),
+                    _cur->elist[3*i+3],
+                    _cur->elist[3*i+2],
+                    _cur->elist[3*i+1],
+                    blosQual);
+    Rec2DDataChange *dc = Rec2DData::getNewDataChange();
+    std::vector<Rec2DAction*> *v = NULL;
+    ra->apply(dc, v);
+    drawStateOrigin();
+  }
+  
+  _noProblemIfObsolete = false;
+  Msg::Info("Recombine2D Blossom Quality %d => %d", Rec2DData::getBlosQual(), 100*_cur->elist[0]-Rec2DData::getBlosQual());
+  Msg::Info("vs Heuristic Blossom Quality %d", blosQual);
+  if (blosQual == 100*_cur->elist[0]-Rec2DData::getBlosQual())
+    Msg::Info("It is ok :-)");
+  else
+    Msg::Info("Not ok :-(...");
+}
+
 //bool Recombine2D::developTree()
 //{
 //  Rec2DNode root(NULL, NULL);
@@ -755,6 +805,8 @@ void Recombine2D::compareWithBlossom()
   recombineWithBlossom(_gf, .0, 1.1, elist, t2n);
   _data->_quad = _gf->quadrangles;
   Recombine2D::drawStateOrigin();
+  __wait(3);
+  drawState(.0,-1.1);
   setStrategy(3);
   int num = 2;
   double dx = .0, dy = .0, time = Cpu();
@@ -1222,6 +1274,15 @@ Rec2DAction* Rec2DData::getOneAction()
   return NULL;
 }
 
+void Rec2DData::getElementsOneAction(std::vector<Rec2DElement*> &vec)
+{
+  vec.clear();
+  std::set<Rec2DElement*>::iterator it = _cur->_elementWithOneAction.begin();
+  while (it != _cur->_elementWithOneAction.end()) {
+    vec.push_back(*it);
+  }
+}
+
 void Rec2DData::getUniqueOneActions(std::vector<Rec2DAction*> &vec)
 {
   std::set<Rec2DElement*> elemWOA = _cur->_elementWithOneAction;
@@ -2390,7 +2451,7 @@ void Rec2DTwoTri2Quad::apply(Rec2DDataChange *rdc,
                              bool color) const
 {
   //I(( "applying Recombine |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum() ));
-  if (isObsolete()) {
+  if (isObsolete() && !Recombine2D::canIsolateTriangle()) {
     printIdentity();
     int p[4];
     p[0] = _vertices[0]->getParity();
@@ -4811,6 +4872,475 @@ MQuadrangle* Rec2DElement::_createQuad() const
   return new MQuadrangle(v1, v2, v3, v4);
 }
 
+/**  Rec2DAlgo  **/
+/*****************/
+namespace Rec2DAlgo {
+void execute()
+{
+  using namespace data;
+
+  if (_initial || _current) {
+    Msg::Error("[Rec2DAlgo] Already have a sequence, cannot execute");
+    return;
+  }
+  _initial = new Node();
+  _current = _initial;
+
+  while (func::lookAhead()) {
+    func::chooseBestSequence();
+  }
+}
+
+void setParam(int horizon, int code)
+{
+  using namespace data;
+
+  char code_root = static_cast<char>(code);
+  char code_tree = static_cast<char>(code >> 8);
+
+  Msg::Info("%d -> %d & %d", code, code_root, code_tree);
+  /*IT IS SHIT !
+  int nr = 0; //3
+  int np = 0; //2
+  int n = nr * 8;
+  _horizon = horizon;
+  _r_std_search     = code % n % nr;
+  _rdo_best         = code % n / nr % 2;
+  _rdo_one_search   = code % n / nr / 2 % 2;
+  _rdo_tree_search  = code % n / nr / 4 % 2;
+  _p_std_search     = code / n % np;
+  _pdo_best         = code / n / np % 2;
+  _pdo_one_search   = code / n / np / 2 % 2;
+  _pdo_tree_search  = code / n / np / 4 % 2;*/
+
+  /*rand / / : 0,1,2
+   *best / / : 3,4,5
+   *rand v / : 6,7,8
+   *best v / : 9,10,11
+   *rand / v : 12,13,14
+   *best / v : 15,16,17
+   *rand v v : 18,19,20
+   *best v v : 21,22,23
+   *
+   *rand / / : 0->23 , 24->47
+   *best / / : 48->71 , 72->95
+   *rand v / : ..
+   *best v / : ..
+   *rand / v : ..
+   *best / v : ..
+   *rand v v : ..
+   *best v v : ..
+   */
+}
+
+namespace data {
+  bool rdo_tree_search = false;
+  bool rdo_one_search = false;
+  int _r_std_search = 0;
+  bool _rdo_best = false;
+  bool _pdo_tree_search = false;
+  bool _pdo_one_search = false;
+  int _p_std_search = 0;
+  bool _pdo_best = false;
+  int _horizon = 0;
+  Node *_current = NULL;
+  Node *_initial = NULL;
+  std::vector<Node*> sequence;
+}
+
+namespace func {
+  using namespace data;
+
+  bool lookAhead()
+  {
+    _current->goAhead(0);
+    return _current->numChildren();
+  }
+
+  void chooseBestSequence()
+  {
+    Node *next = _current->getNodeBestSequence();
+    if (_current->choose(next))
+      _current = next;
+    else
+      Msg::Fatal("Wrong child node in lookahead tree");
+  }
+
+  Rec2DElement* best(std::vector<Rec2DElement*> &available)
+  {
+    std::vector<Rec2DAction*> actions;
+    for (unsigned int i = 0; i < available.size(); ++i)
+      available[i]->getMoreUniqueActions(actions);
+
+    std::vector<Rec2DElement*> candidate;
+    (*std::max_element(actions.begin(), actions.end(), lessRec2DAction()))
+        ->getElements(candidate);
+
+    std::vector<Rec2DElement*> unionBest;
+    for (unsigned int i = 0; i < candidate.size(); ++i) {
+      for (unsigned int j = 0; j < available.size(); ++j) {
+        if (candidate[i] == available[j]) {
+          unionBest.push_back(candidate[i]);
+        }
+      }
+    }
+    return unionBest[rand() % unionBest.size()];
+  }
+
+  Rec2DElement* random(std::vector<Rec2DElement*> &v)
+  {
+    return v[rand() % v.size()];
+  }
+
+  void searchForOne(std::vector<Rec2DElement*> &triangles)
+  {
+    Rec2DData::getElementsOneAction(triangles);
+  }
+
+  void searchForRootStd(std::vector<Rec2DElement*> &triangles)
+  {
+    switch (_r_std_search) {
+    case 1:
+      searchForAll(triangles);
+      break;
+    case 2:
+      searchForQAll(triangles);
+      break;
+    case 3:
+      searchForQFirst(triangles);
+      break;
+    case 4:
+      searchForQLast(triangles);
+      break;
+    default:
+      Msg::Error("Wrong root standard search");
+    }
+  }
+
+  void searchForPlusStd(std::vector<Rec2DElement*> &triangles)
+  {
+    switch (_p_std_search) {
+    case 1:
+      searchForAll(triangles);
+      break;
+    case 2:
+      searchForQAll(triangles);
+      break;
+    case 3:
+      searchForQFirst(triangles);
+      break;
+    case 4:
+      searchForTAll(triangles);
+      break;
+    case 5:
+      searchForTFirst(triangles);
+      break;
+    case 6:
+      searchForTLast(triangles);
+      break;
+    default:
+      Msg::Error("Wrong plus standard search");
+    }
+  }
+
+  void searchForAll(std::vector<Rec2DElement*> &triangles)
+  {
+    Rec2DData::copyElements(triangles);
+  }
+
+  void searchForQAll(std::vector<Rec2DElement*> &triangles) {
+    searchForTAll(triangles);
+    Node *n = data::_initial;
+    while (n != data::_current) {
+      n = n->getChild();
+      std::vector<Rec2DElement*> elem;
+      n->getAction()->getNeighbElemWithActions(elem);
+      insertUnique(elem, triangles);
+    }
+  }
+
+  void searchForQFirst(std::vector<Rec2DElement*> &triangles) {
+    triangles.clear();
+    Node *n = data::_initial;
+    while (triangles.empty() && n != data::_current) {
+      n = n->getChild();
+      std::vector<Rec2DElement*> elem;
+      n->getAction()->getNeighbElemWithActions(triangles);
+    }
+    if (triangles.empty()) searchForTFirst(triangles);
+  }
+
+  void searchForQLast(std::vector<Rec2DElement*> &triangles) {
+    _current->getAction()->getNeighbElemWithActions(triangles);
+  }
+
+  void searchForTAll(std::vector<Rec2DElement*> &triangles) {
+    triangles.clear();
+    for (unsigned int i = 1; i < data::sequence.size(); ++i) {
+      std::vector<Rec2DElement*> elem;
+      data::sequence[i]->getAction()->getNeighbElemWithActions(elem);
+      insertUnique(elem, triangles);
+    }
+  }
+
+  void searchForTFirst(std::vector<Rec2DElement*> &triangles) {
+    triangles.clear();
+    int i = 1;
+    while (triangles.empty() && i < data::sequence.size()) {
+      data::sequence[i]->getAction()->getNeighbElemWithActions(triangles);
+    }
+  }
+
+  void searchForTLast(std::vector<Rec2DElement*> &triangles) {
+    data::sequence.back()->getAction()->getNeighbElemWithActions(triangles);
+  }
+
+  void insertUnique(std::vector<Rec2DElement*> &from,
+                    std::vector<Rec2DElement*> &to) {
+    for (unsigned int i = 0; i < from.size(); ++i) {
+      unsigned int j = 0;
+      while (j < to.size() && from[i] != to[j]) ++j;
+      if (j == to.size()) {
+        to.push_back(from[i]);
+      }
+    }
+  }
+}
+
+Node* Node::getNodeBestSequence()
+{
+  // return NULL if no children;
+  Node *bestNode = NULL;
+  int maxLeafQual = 0; // /!\ ok if quality criterion is >= 0
+
+  for (unsigned int i = 0; i < _children.size(); ++i) {
+    int qual = _children[i]->getMaxLeafQual();
+    if (qual > maxLeafQual) {
+      bestNode = _children[i];
+      maxLeafQual = qual;
+    }
+  }
+  return bestNode;
+}
+
+int Node::getMaxLeafQual() const
+{
+  if (_children.empty()) return _quality;
+
+  int maxLeafQual = 0; // /!\ ok if quality criterion is >= 0
+  for (unsigned int i = 0; i < _children.size(); ++i) {
+    maxLeafQual = std::max(maxLeafQual, _children[i]->getMaxLeafQual());
+  }
+  return 1;
+}
+
+bool Node::choose(Node *node)
+{
+  if (!node) return false;
+
+  for (unsigned int i = 0; i < _children.size(); ++i) {
+    if (_children[i] == node) {
+      _children[i] = NULL;
+      for (unsigned int j = 0; j < _children.size(); ++j) {
+        delete _children[j]; // sufficient ?
+      }
+      _children.clear();
+      _children.push_back(node);
+      return true;
+    }
+  }
+  return false;
+}
+
+Node::Node() : _ra(NULL), _dataChange(NULL), _createdActions(NULL)
+{
+  _quality = Rec2DData::getGlobalQuality();
+}
+
+Node::Node(Rec2DAction *action) : _ra(action), _dataChange(NULL),
+                                  _createdActions(NULL)
+{
+  _quality = Rec2DData::getGlobalQuality() + _ra->getRealReward();
+}
+
+void Node::goAhead(int depth)
+{
+  if (depth > data::_horizon - 1 || depth < 0) {
+    Msg::Fatal("the fuck..");
+  }
+
+  if (depth == 0) {
+    branch_root();
+    return;
+  }
+  // else
+  // 1) Make changes
+  // 2) branch on children
+  // 3) revert changes
+
+  _dataChange = Rec2DData::getNewDataChange();
+  _ra->apply(_dataChange, _createdActions);
+  if (_createdActions) {
+    for (unsigned int i = 0; i < _createdActions->size(); ++i)
+      (*_createdActions)[i]->addPointing();
+  }
+
+  branch(depth);
+
+  if (!Rec2DData::revertDataChange(_dataChange))
+    Msg::Error("Unreverted changes");
+  else
+    Recombine2D::incNumChange();
+  _dataChange = NULL;
+}
+
+void Node::branch_root()
+{
+  using namespace data;
+  using namespace func;
+  sequence.push_back(this);
+
+  // 1) search a set of triangles
+  int searchType = 0;
+  std::vector<Rec2DElement*> candidateTriangle;
+
+  while (candidateTriangle.empty()) {
+    switch (searchType) {
+    case 0:
+      if (rdo_tree_search) {
+        for (unsigned int i = 0; i < _children.size(); ++i)
+          _children[i]->goAhead(1);
+      }
+      else {
+        for (unsigned int i = 0; i < _children.size(); ++i)
+          delete _children[i]; //is it sufficient ?
+        _children.clear();
+      }
+
+    case 1:
+      if (rdo_one_search)
+        searchForOne(candidateTriangle);
+      break;
+
+    case 2:
+      searchForRootStd(candidateTriangle);
+      break;
+
+    case 3:
+      searchForAll(candidateTriangle);
+      break;
+
+    case 4:
+      Msg::Error("Think I should not be here");
+      // because searchForAll() fails only at the end
+      // and I think branch_root() is not called at the end
+      return;
+
+    default:
+      Msg::Fatal("No reason to be here");
+    }
+  }
+
+  // 2) take actions of the best or a random
+  Rec2DElement *rt;
+  if (_rdo_best)
+    rt = best(candidateTriangle);
+  else
+    rt = random(candidateTriangle);
+  std::vector<Rec2DAction*> actions;
+  rt->getActions(actions);
+
+  // 3) branch on the actions
+  for (unsigned int i = 0; i < actions.size(); ++i)
+    _children.push_back(new Node(actions[i]));
+
+  if (1 < _horizon) {
+    for (unsigned int i = 0; i < _children.size(); ++i)
+      _children[i]->goAhead(1);
+  }
+
+  if (sequence.back() != this)
+    Msg::Fatal("Aaargh");
+  sequence.pop_back();
+}
+
+void Node::branch(int depth)
+{
+  if (depth > data::_horizon || depth < 1) {
+    if (depth == 0) {
+      Msg::Error("branch() cannot be called for root, use branch_root()");
+      return;
+    }
+    Msg::Fatal("the fuck !");
+  }
+  using namespace data;
+  using namespace func;
+  sequence.push_back(this);
+
+  // 1) search a set of triangles
+  int searchType = 0;
+  std::vector<Rec2DElement*> candidateTriangle;
+
+  while (candidateTriangle.empty()) {
+    switch (searchType) {
+    case 0:
+      if (_pdo_tree_search) {
+        if (_children.size()) {
+          for (unsigned int i = 0; i < _children.size(); ++i)
+            _children[i]->goAhead(depth + 1);
+        }
+        else return;
+      }
+      else {
+        for (unsigned int i = 0; i < _children.size(); ++i)
+          delete _children[i]; //is it sufficient ?
+        _children.clear();
+      }
+
+    case 1:
+      if (_pdo_one_search)
+        searchForOne(candidateTriangle);
+      break;
+
+    case 2:
+      searchForPlusStd(candidateTriangle);
+      break;
+
+    case 3:
+      searchForAll(candidateTriangle);
+      break;
+
+    case 4:
+      return;
+
+    default:
+      Msg::Fatal("No reason to be here");
+    }
+  }
+
+  // 2) take actions of the best or a random
+  Rec2DElement *rt;
+  if (_pdo_best)
+    rt = best(candidateTriangle);
+  else
+    rt = random(candidateTriangle);
+  std::vector<Rec2DAction*> actions;
+  rt->getActions(actions);
+
+  // 3) branch on the actions
+  for (unsigned int i = 0; i < actions.size(); ++i)
+    _children.push_back(new Node(actions[i]));
+
+  if (depth + 1 < _horizon) {
+    for (unsigned int i = 0; i < _children.size(); ++i)
+      _children[i]->goAhead(depth + 1);
+  }
+
+  if (sequence.back() != this)
+    Msg::Fatal("Aaargh");
+  sequence.pop_back();
+}
+}
 
 /**  Rec2DNode  **/
 /*****************/
@@ -5065,7 +5595,7 @@ void Rec2DNode::printIdentity() const
 
 void Rec2DNode::printSequence() const
 {
-  static int denom = 3;
+  static int denom = 5;
   //_ra->color(183+72*(double)(_depth+2)/denom, 255*(1-(double)(_depth+2)/denom), 169*(1-(double)(_depth+2)/denom));
   _ra->color(255, 255*(1-(double)_depth/denom), 128*(1-(double)_depth/denom));
   if (_son[0]) _son[0]->printSequence();
@@ -5118,10 +5648,11 @@ void Rec2DNode::_makeDevelopments(int depth)
     _notAllQuad = true;
     if (!Recombine2D::revertIfNotAllQuad()) {
       // If not all quad, I can't tell which son is the best...
-      Rec2DNode *tmpNode = _son[i];
-      _son[i] = _son[k2];
+      Msg::Warning("I'm crazy and I don't know what I am doing Oo");
+      Rec2DNode *tmpNode = _son[0];
+      _son[0] = _son[k2];
       _son[k2] = tmpNode;
-      _bestSeqReward = _son[i]->_getBestSequenceReward();
+      _bestSeqReward = _son[0]->_getBestSequenceReward();
       ++k2;
     }
   }
diff --git a/Mesh/meshGFaceRecombine.h b/Mesh/meshGFaceRecombine.h
index 94c7cc8f61..e6feff281d 100644
--- a/Mesh/meshGFaceRecombine.h
+++ b/Mesh/meshGFaceRecombine.h
@@ -42,6 +42,7 @@
   #include "meshGFaceOptimize.h"
 #endif
 #include <fstream>
+#include <vector>
 
 
 class Rec2DNode;
@@ -94,8 +95,9 @@ class Recombine2D {
     
     bool _checkIfNotAllQuad; // Check if action implies triangle isolation
     bool _avoidIfNotAllQuad; // Don't apply action if it implies triangle isolation
-    bool _revertIfNotAllQuad; // Be all quad at any price (can it be not unefficient ?)
+    bool _revertIfNotAllQuad; // Be all quad at any price (can it be not totally unefficient ?)
     bool _oneActionHavePriority; // Tracks and prioritises elements with 1 action
+    bool _noProblemIfObsolete; // For recombineSameAsHeuristic
     
     int _weightEdgeBase;
     int _weightEdgeQuad;
@@ -123,6 +125,7 @@ class Recombine2D {
     bool recombine();
     double recombine(int depth);
     void recombineSameAsBlossom(); // just to check blossomQual
+    void recombineSameAsHeuristic();
     //bool developTree();
     static void nextTreeActions(std::vector<Rec2DAction*>&,
                                 const std::vector<Rec2DElement*> &neighbours,
@@ -158,6 +161,7 @@ class Recombine2D {
     static inline bool avoidIfNotAllQuad() {return _cur->_avoidIfNotAllQuad;}
     static inline bool revertIfNotAllQuad() {return _cur->_revertIfNotAllQuad;}
     static inline bool priorityOfOneAction() {return _cur->_oneActionHavePriority;}
+    static inline bool canIsolateTriangle() {return _cur->_noProblemIfObsolete;}
     
     // Get/Set Weights
     static inline int getWeightEdgeBase() {return _cur->_weightEdgeBase;}
@@ -224,8 +228,8 @@ class Rec2DData {
         unsigned int position;
         Action(const Rec2DAction *ra, unsigned int pos)
           : action(ra), position(pos) {
-            static int a = -1;
-            if (++a < 1) Msg::Warning("FIXME: position is supefluous in this case (iterators are sufficient)");
+            static int a = 0;
+            if (++a == 1) Msg::Warning("FIXME: position is supefluous in this case (iterators are sufficient)");
           }
     };
     template<class T> friend void std::swap(T&, T&);
@@ -339,6 +343,7 @@ class Rec2DData {
     static void rmvHasOneAction(const Rec2DElement*);
     static bool hasHasOneAction(const Rec2DElement*);
     static int getNumOneAction();
+    static void getElementsOneAction(std::vector<Rec2DElement*> &vec);
     static Rec2DAction* getOneAction();
     static void getUniqueOneActions(std::vector<Rec2DAction*>&);
     
@@ -392,6 +397,9 @@ class Rec2DData {
     static inline int getNumElement() {return _cur->_elements.size();}
     
     // Miscellaneous
+    static void copyElements(std::vector<Rec2DElement*> &v) {
+      v = _cur->_elements;
+    }
 #ifdef REC2D_RECO_BLOS
     static Rec2DElement* getRElement(MElement*);
 #endif
@@ -1023,6 +1031,96 @@ class Rec2DElement {
 };
 
 //
+
+namespace Rec2DAlgo {
+  class Node;
+
+  void setParam(int horizon, int code);
+  void execute();
+
+  namespace data {
+    extern bool rdo_tree_search, rdo_one_search;
+    extern int _r_std_search;
+    /* 1 : all-search
+     * 2 : qall-search
+     * 3 : qfirst-search
+     * 4 : qlast-search
+     */
+    extern bool _rdo_best;
+
+    extern bool _pdo_tree_search, _pdo_one_search;
+    extern int _p_std_search;
+    /* 1 : all-search
+     * 2 : qall-search
+     * 3 : qfirst-search
+     * 4 : tall-search
+     * 5 : tfirst-search
+     * 6 : tlast-search
+     */
+    extern bool _pdo_best;
+
+    extern int _horizon;
+
+    extern Node *_initial;
+    extern Node *_current;
+
+    extern std::vector<Node*> sequence;
+  }
+
+  namespace func {
+    bool lookAhead(); // false if no lookahead tree
+    void chooseBestSequence();
+
+    // functions search
+    void searchForOne(std::vector<Rec2DElement*>&);
+    void searchForRootStd(std::vector<Rec2DElement*>&);
+    void searchForPlusStd(std::vector<Rec2DElement*>&);
+    void searchForAll(std::vector<Rec2DElement*>&);
+    void searchForQAll(std::vector<Rec2DElement*>&);
+    void searchForQFirst(std::vector<Rec2DElement*>&);
+    void searchForQLast(std::vector<Rec2DElement*>&);
+    void searchForTAll(std::vector<Rec2DElement*>&);
+    void searchForTFirst(std::vector<Rec2DElement*>&);
+    void searchForTLast(std::vector<Rec2DElement*>&);
+
+    Rec2DElement* random(std::vector<Rec2DElement*> &v);
+    Rec2DElement* best(std::vector<Rec2DElement*>&);
+
+    void insertUnique(std::vector<Rec2DElement*> &from,
+                      std::vector<Rec2DElement*> &to);
+  }
+
+  class Node {
+  private :
+    int _quality;
+    Rec2DAction *_ra;
+    Rec2DDataChange *_dataChange;
+    std::vector<Rec2DAction*> *_createdActions;
+    std::vector<Node*> _children;
+
+  public :
+    Node();
+    Node(Rec2DAction*);
+
+    Node* getChild() const {
+      if (_children.size() != 0) {
+        Msg::Error("Do not have only one child");
+        return NULL;
+      }
+      return _children[0];
+    }
+    Rec2DAction* getAction() const {return _ra;}
+    int numChildren() const {return _children.size();}
+    Node* getNodeBestSequence();
+    bool choose(Node*);
+    int getMaxLeafQual() const;
+
+    void branch_root();
+    void branch(int depth);
+    void goAhead(int depth);
+  };
+}
+
 class Rec2DNode {
   private :
     Rec2DNode *_father;
@@ -1110,8 +1208,8 @@ class Rec2DNode {
       _dataChange = Rec2DData::getNewDataChange();
       _ra->apply(_dataChange, _createdActions);
       _dataChange = NULL;
-      static int a = -1;
-      if (++a < 1) Msg::Warning("FIXME pas propre du tout");
+      static int a = 0;
+      if (++a == 1) Msg::Warning("FIXME pas propre du tout");
     }
     inline bool _isNotAllQuad() const {return _notAllQuad;}
 };
-- 
GitLab