فهرست منبع

added testcase for downhill simplex optimization

Alexander Freytag 12 سال پیش
والد
کامیت
b5dc15c81f
3فایلهای تغییر یافته به همراه276 افزوده شده و 0 حذف شده
  1. 89 0
      tests/Makefile.inc
  2. 152 0
      tests/TestDownhillSimplex.cpp
  3. 35 0
      tests/TestDownhillSimplex.h

+ 89 - 0
tests/Makefile.inc

@@ -0,0 +1,89 @@
+# BINARY-DIRECTORY-MAKEFILE
+# conventions:
+# - there are no subdirectories, they are ignored!
+# - all ".C", ".cpp" and ".c" files in the current directory are considered
+#   independent binaries, and linked as such.
+# - the binaries depend on the library of the parent directory
+# - the binary names are created with $(BINNAME), i.e. it will be more or less
+#   the name of the .o file
+# - all binaries will be added to the default build list ALL_BINARIES
+
+# --------------------------------
+# - remember the last subdirectory
+#
+# set the variable $(SUBDIR) correctly to the current subdirectory. this
+# variable can be used throughout the current makefile.inc. The many 
+# SUBDIR_before, _add, and everything are only required so that we can recover
+# the previous content of SUBDIR before exitting the makefile.inc
+
+SUBDIR_add:=$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
+SUBDIR_before:=$(SUBDIR)
+SUBDIR:=$(strip $(SUBDIR_add))
+SUBDIR_before_$(SUBDIR):=$(SUBDIR_before)
+
+# ------------------------
+# - include subdirectories
+#
+# note the variables $(SUBDIRS_OF_$(SUBDIR)) are required later on to recover
+# the dependencies automatically. if you handle dependencies on your own, you
+# can also dump the $(SUBDIRS_OF_$(SUBDIR)) variable, and include the
+# makefile.inc of the subdirectories on your own...
+
+#SUBDIRS_OF_$(SUBDIR):=$(patsubst %/Makefile.inc,%,$(wildcard $(SUBDIR)*/Makefile.inc))
+#include $(SUBDIRS_OF_$(SUBDIR):%=%/Makefile.inc)
+
+# ----------------------------
+# - include local dependencies
+#
+# include the libdepend.inc file, which gives additional dependencies for the
+# libraries and binaries. additionally, an automatic dependency from the library
+# of the parent directory is added (commented out in the code below).
+
+-include $(SUBDIR)libdepend.inc
+
+PARENTDIR:=$(patsubst %/,%,$(dir $(patsubst %/,%,$(SUBDIR))))
+$(call PKG_DEPEND_INT,$(PARENTDIR))
+$(call PKG_DEPEND_EXT,CPPUNIT)
+
+# ---------------------------
+# - objects in this directory
+#
+# the use of the variable $(OBJS) is not mandatory. it is mandatory however
+# to update $(ALL_OBJS) in a way that it contains the path and name of
+# all objects. otherwise we can not include the appropriate .d files.
+
+OBJS:=$(patsubst %.cpp,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.cpp))) \
+      $(patsubst %.C,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.C))) \
+      $(shell grep -ls Q_OBJECT $(SUBDIR)*.h | sed -e's@^@/@;s@.*/@$(OBJDIR)moc_@;s@\.h$$@.o@') \
+      $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.c)))
+ALL_OBJS += $(OBJS)
+
+# ----------------------------
+# - binaries in this directory
+#
+# output of binaries in this directory. none of the variables has to be used.
+# but everything you add to $(ALL_LIBRARIES) and $(ALL_BINARIES) will be
+# compiled with `make all`. be sure again to add the files with full path.
+
+CHECKS:=$(BINDIR)$(call LIBNAME,$(SUBDIR))
+ALL_CHECKS+=$(CHECKS)
+
+# ---------------------
+# - binary dependencies
+#
+# there is no way of determining the binary dependencies automatically, so we
+# follow conventions. each binary depends on the corresponding .o file and
+# on the libraries specified by the INTLIBS/EXTLIBS. these dependencies can be
+# specified manually or they are automatically stored in a .bd file.
+
+$(foreach head,$(wildcard $(SUBDIR)*.h),$(eval $(shell grep -q Q_OBJECT $(head) && echo $(head) | sed -e's@^@/@;s@.*/\(.*\)\.h$$@$(BINDIR)\1:$(OBJDIR)moc_\1.o@')))
+$(eval $(foreach c,$(CHECKS),$(c):$(BUILDDIR)$(CPPUNIT_MAIN_OBJ) $(OBJS) $(call PRINT_INTLIB_DEPS,$(c),.a)))
+
+# -------------------
+# - subdir management
+#
+# as the last step, always add this line to correctly recover the subdirectory
+# of the makefile including this one!
+
+SUBDIR:=$(SUBDIR_before_$(SUBDIR))
+

+ 152 - 0
tests/TestDownhillSimplex.cpp

@@ -0,0 +1,152 @@
+#ifdef NICE_USELIB_CPPUNIT
+
+#include <string>
+#include <exception>
+#include <map>
+
+#include "TestDownhillSimplex.h"
+
+using namespace std;
+
+const bool verboseStartEnd = true;
+// const bool verbose = true;
+const bool verbose = false;
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TestDownhillSimplex );
+
+void TestDownhillSimplex::setUp() {
+}
+
+void TestDownhillSimplex::tearDown() {
+}
+
+//define a simple cost function for one-dimensional or two-dimensional data
+class MyCostFunction : public CostFunction
+{
+  public: 
+  
+   MyCostFunction(const int & dim) : CostFunction(dim)
+   {
+   }
+
+   virtual double evaluate(const optimization::matrix_type & x)
+   {
+     double f;
+     
+     if (verbose)
+      std::cerr << x.rows() << " x " << x.cols() << std::endl;
+     if ( x.rows() == 1 )
+     {
+       if (verbose)
+        std::cerr << "current position: " << x[0][0] << std::endl;
+       
+       //our cost function is f(x) = (x-5)^2
+       f = pow(x[0][0] - 4.2, 2.0);
+    
+       if (verbose)
+        std::cerr << "function value: " << f << std::endl;
+
+     } 
+     //two-dimensional data
+     else {
+       if (verbose)
+         std::cerr << "current position: " << x[0][0] << " " << x[1][0] << std::endl;
+       
+       //our cost function is f(x,y) = (x-4.7)^2 + (y-1.1)^2
+       f = pow(x[0][0] - 4.7, 2.0) + pow( x[1][0] - 1.1, 2.0 );
+       
+       if (verbose)
+         std::cerr << "function value: " << f << std::endl;
+     }
+     return f;
+   }
+
+
+};
+
+void TestDownhillSimplex::testDHS_1Dim ()
+{
+  
+  if (verboseStartEnd)
+    std::cerr << "================== TestDownhillSimplex::testDHS_1Dim ===================== " << std::endl;
+  
+  int dim (1);
+  
+  CostFunction *func = new MyCostFunction(dim); 
+   
+  //initial guess: 2.0
+  optimization::matrix_type initialParams (dim, 1);
+  initialParams.Set(2.0);
+
+  //we search with step-width of 1.0
+  optimization::matrix_type scales (dim, 1);
+  scales.Set(1.0);
+
+  //setup the optimization problem
+  SimpleOptProblem optProblem ( func, initialParams, scales );
+  
+  DownhillSimplexOptimizer optimizer;
+  //actually, this has no effect at all
+  optimizer.setMaxNumIter(true, 100);
+  optimizer.optimizeProb ( optProblem );  
+  
+  optimization::matrix_type optimizedParams (optProblem.getAllCurrentParams());
+  
+  double goal(4.2);  
+  
+  if (verbose)
+    std::cerr << "1d optimization -- result " << optimizedParams[0][0] << " -- goal: " << goal << std::endl;
+
+  CPPUNIT_ASSERT_DOUBLES_EQUAL( optimizedParams[0][0], goal, 1e-7 /* tolerance */);
+
+  if (verboseStartEnd)
+    std::cerr << "================== TestDownhillSimplex::testDHS_1Dim done ===================== " << std::endl;  
+
+}
+
+void TestDownhillSimplex::testDHS_2Dim() 
+{
+  
+  if (verboseStartEnd)
+    std::cerr << "================== TestDownhillSimplex::testDHS_2Dim ===================== " << std::endl;
+  
+  int dim (2);  
+  
+  CostFunction *func = new MyCostFunction(dim); 
+   
+  //initial guess: 2.0
+  optimization::matrix_type initialParams (dim, 1);
+  initialParams.Set(2.0);
+
+  //we search with step-width of 1.0
+  optimization::matrix_type scales (dim, 1);
+  scales.Set(1.0);
+
+  //setup the optimization problem
+  SimpleOptProblem optProblem ( func, initialParams, scales );
+  
+  DownhillSimplexOptimizer optimizer;
+  //actually, this has no effect at all
+  optimizer.setMaxNumIter(true, 100);
+  optimizer.optimizeProb ( optProblem );  
+  
+  optimization::matrix_type optimizedParams (optProblem.getAllCurrentParams());
+
+  double goalFirstDim(4.7);
+  double goalSecondDim(1.1);
+  
+  if (verbose)
+  {
+    std::cerr << "2d optimization  1st dim-- result " << optimizedParams[0][0] << " -- goal: " << goalFirstDim << std::endl;
+    std::cerr << "2d optimization  1st dim-- result " << optimizedParams[1][0] << " -- goal: " << goalSecondDim << std::endl;
+  }
+
+  CPPUNIT_ASSERT_DOUBLES_EQUAL( optimizedParams[0][0], goalFirstDim, 1e-7 /* tolerance */);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL( optimizedParams[1][0], goalSecondDim, 1e-7 /* tolerance */);
+  
+  
+  if (verboseStartEnd)
+    std::cerr << "================== TestDownhillSimplex::testDHS_2Dim done ===================== " << std::endl;  
+}
+
+#endif

+ 35 - 0
tests/TestDownhillSimplex.h

@@ -0,0 +1,35 @@
+#ifndef _TESTDOWNHILLSIMPLEX_H
+#define _TESTDOWNHILLSIMPLEX_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "optimization/DownhillSimplexOptimizer.h"
+
+/**
+ * CppUnit-Testcase. 
+ */
+class TestDownhillSimplex : public CppUnit::TestFixture {
+
+    CPPUNIT_TEST_SUITE( TestDownhillSimplex );
+    
+    CPPUNIT_TEST(testDHS_1Dim);
+    CPPUNIT_TEST(testDHS_2Dim);
+    
+    CPPUNIT_TEST_SUITE_END();
+  
+ private:
+ 
+ public:
+    void setUp();
+    void tearDown();
+
+    /**
+    * Constructor / Destructor testing 
+    */  
+    
+    void testDHS_1Dim();
+
+    void testDHS_2Dim();
+
+};
+
+#endif // _TESTFASTHIK_H