simplex_downhill.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /***********************************************************************
  2. * Software License Agreement (BSD License)
  3. *
  4. * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
  5. * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
  6. *
  7. * THE BSD LICENSE
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *************************************************************************/
  30. #ifndef OPENCV_FLANN_SIMPLEX_DOWNHILL_H_
  31. #define OPENCV_FLANN_SIMPLEX_DOWNHILL_H_
  32. //! @cond IGNORED
  33. namespace cvflann
  34. {
  35. /**
  36. Adds val to array vals (and point to array points) and keeping the arrays sorted by vals.
  37. */
  38. template <typename T>
  39. void addValue(int pos, float val, float* vals, T* point, T* points, int n)
  40. {
  41. vals[pos] = val;
  42. for (int i=0; i<n; ++i) {
  43. points[pos*n+i] = point[i];
  44. }
  45. // bubble down
  46. int j=pos;
  47. while (j>0 && vals[j]<vals[j-1]) {
  48. swap(vals[j],vals[j-1]);
  49. for (int i=0; i<n; ++i) {
  50. swap(points[j*n+i],points[(j-1)*n+i]);
  51. }
  52. --j;
  53. }
  54. }
  55. /**
  56. Simplex downhill optimization function.
  57. Preconditions: points is a 2D mattrix of size (n+1) x n
  58. func is the cost function taking n an array of n params and returning float
  59. vals is the cost function in the n+1 simplex points, if NULL it will be computed
  60. Postcondition: returns optimum value and points[0..n] are the optimum parameters
  61. */
  62. template <typename T, typename F>
  63. float optimizeSimplexDownhill(T* points, int n, F func, float* vals = NULL )
  64. {
  65. const int MAX_ITERATIONS = 10;
  66. CV_DbgAssert(n>0);
  67. T* p_o = new T[n];
  68. T* p_r = new T[n];
  69. T* p_e = new T[n];
  70. int alpha = 1;
  71. int iterations = 0;
  72. bool ownVals = false;
  73. if (vals == NULL) {
  74. ownVals = true;
  75. vals = new float[n+1];
  76. for (int i=0; i<n+1; ++i) {
  77. float val = func(points+i*n);
  78. addValue(i, val, vals, points+i*n, points, n);
  79. }
  80. }
  81. int nn = n*n;
  82. while (true) {
  83. if (iterations++ > MAX_ITERATIONS) break;
  84. // compute average of simplex points (except the highest point)
  85. for (int j=0; j<n; ++j) {
  86. p_o[j] = 0;
  87. for (int i=0; i<n; ++i) {
  88. p_o[i] += points[j*n+i];
  89. }
  90. }
  91. for (int i=0; i<n; ++i) {
  92. p_o[i] /= n;
  93. }
  94. bool converged = true;
  95. for (int i=0; i<n; ++i) {
  96. if (p_o[i] != points[nn+i]) {
  97. converged = false;
  98. }
  99. }
  100. if (converged) break;
  101. // trying a reflection
  102. for (int i=0; i<n; ++i) {
  103. p_r[i] = p_o[i] + alpha*(p_o[i]-points[nn+i]);
  104. }
  105. float val_r = func(p_r);
  106. if ((val_r>=vals[0])&&(val_r<vals[n])) {
  107. // reflection between second highest and lowest
  108. // add it to the simplex
  109. Logger::info("Choosing reflection\n");
  110. addValue(n, val_r,vals, p_r, points, n);
  111. continue;
  112. }
  113. if (val_r<vals[0]) {
  114. // value is smaller than smallest in simplex
  115. // expand some more to see if it drops further
  116. for (int i=0; i<n; ++i) {
  117. p_e[i] = 2*p_r[i]-p_o[i];
  118. }
  119. float val_e = func(p_e);
  120. if (val_e<val_r) {
  121. Logger::info("Choosing reflection and expansion\n");
  122. addValue(n, val_e,vals,p_e,points,n);
  123. }
  124. else {
  125. Logger::info("Choosing reflection\n");
  126. addValue(n, val_r,vals,p_r,points,n);
  127. }
  128. continue;
  129. }
  130. if (val_r>=vals[n]) {
  131. for (int i=0; i<n; ++i) {
  132. p_e[i] = (p_o[i]+points[nn+i])/2;
  133. }
  134. float val_e = func(p_e);
  135. if (val_e<vals[n]) {
  136. Logger::info("Choosing contraction\n");
  137. addValue(n,val_e,vals,p_e,points,n);
  138. continue;
  139. }
  140. }
  141. {
  142. Logger::info("Full contraction\n");
  143. for (int j=1; j<=n; ++j) {
  144. for (int i=0; i<n; ++i) {
  145. points[j*n+i] = (points[j*n+i]+points[i])/2;
  146. }
  147. float val = func(points+j*n);
  148. addValue(j,val,vals,points+j*n,points,n);
  149. }
  150. }
  151. }
  152. float bestVal = vals[0];
  153. delete[] p_r;
  154. delete[] p_o;
  155. delete[] p_e;
  156. if (ownVals) delete[] vals;
  157. return bestVal;
  158. }
  159. }
  160. //! @endcond
  161. #endif //OPENCV_FLANN_SIMPLEX_DOWNHILL_H_