Skip to content
Snippets Groups Projects
SobolSequenceTest.h 3.46 KiB
Newer Older
#ifndef SOBOLSEQUENCETEST_H_
#define SOBOLSEQUENCETEST_H_

#include <cxxtest/TestSuite.h>
#include "MantidKernel/SobolSequence.h"

#include <boost/algorithm/string/predicate.hpp>

using Mantid::Kernel::SobolSequence;

class SobolSequenceTest : public CxxTest::TestSuite
{

public:
  
  void test_That_Object_Construction_Does_Not_Throw()
  {
    TS_ASSERT_THROWS_NOTHING(SobolSequence(1));
  }

  void test_That_Next_For_Two_Generators_Returns_Same_Value()
  {
    SobolSequence gen_1(3), gen_2(3);
    const std::vector<double> seq1 = gen_1.nextPoint();
    const std::vector<double> seq2 = gen_2.nextPoint();

    TS_ASSERT(boost::algorithm::equals(seq1, seq2));
   void test_That_A_Given_Number_Of_Dimensions_Produces_Expected_Sequence()
   {
     SobolSequence randGen(5);

     assert_Sequence_Is_As_Expected_For_Five_Dimensions(randGen);
   }

   void test_That_Restart_Produces_The_Sequence_From_The_Beginning()
   {
     SobolSequence randGen(5);
     doNextValueCalls(20, randGen);
     randGen.restart();

     assert_Sequence_Is_As_Expected_For_Five_Dimensions(randGen);
   }

   void test_Save_Call_Restore_Gives_Sequence_From_Saved_Point()
     doNextValueCalls(25, randGen); // Move from start to test it doesn't just go back to beginning
     randGen.save();
     const size_t ncheck(20);
     auto firstValues = doNextValueCalls(ncheck, randGen);
     randGen.restore();
     auto secondValues = doNextValueCalls(ncheck, randGen);


     for(size_t i = 0; i < ncheck; ++i)
       TS_ASSERT(boost::algorithm::equals(firstValues[i], secondValues[i]));
     }
   }

   void test_Save_Call_Restore_Call_Then_Restore_Gives_Sequence_From_Saved_Point()
   {
     SobolSequence randGen(5);
     doNextValueCalls(25, randGen); // Move from start to test it doesn't just go back to beginning
     randGen.save();
     const size_t ncheck(20);
     auto firstValues = doNextValueCalls(ncheck, randGen);
     randGen.restore();
     doNextValueCalls(ncheck, randGen);
     randGen.restore();
     auto thirdValues = doNextValueCalls(ncheck, randGen);

     for(size_t i = 0; i < ncheck; ++i)
       TS_ASSERT(boost::algorithm::equals(firstValues[i], thirdValues[i]));
   std::vector<std::vector<double>> doNextValueCalls(const unsigned int ncalls, SobolSequence &randGen)
   {
     std::vector<std::vector<double>> values(ncalls);
     for(unsigned int i = 0; i < ncalls; ++i)
     {
       values[i] = randGen.nextPoint();
     }
     return values;
   }
  void assert_Sequence_Is_As_Expected_For_Five_Dimensions(SobolSequence & randGen)
    double expectedValues[3][5] = \
         {0.5,0.5,0.5,0.5,0.5},
         {0.75,0.25,0.75,0.25,0.75},
         {0.25,0.75,0.25,0.75,0.25},
    };
    for( std::size_t i = 0; i < 3; ++i )
    {
      const std::vector<double> randPoint = randGen.nextPoint();
      for( std::size_t j = 0; j < 5; ++j)
        TS_ASSERT_DELTA(randPoint[j], expectedValues[i][j], 1e-12);
class SobolSequenceTestPerformance : public CxxTest::TestSuite
{
public:

  void test_Large_Number_Of_Next_Point_Calls()
  {
    const unsigned int ndimensions(14);
    SobolSequence generator(ndimensions);
    const size_t ncalls = 10000000;
    size_t sumSizes(0); // Make sure the optimizer actuall does the loop
    for(size_t i = 0; i < ncalls; ++i)
    {
      const std::vector<double> & point = generator.nextPoint();
      sumSizes += point.size();
    }
    TS_ASSERT(sumSizes > 0);
  }
};