[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi] test tool for validating actuarial_table implementations
From: |
Vaclav Slavik |
Subject: |
[lmi] test tool for validating actuarial_table implementations |
Date: |
Thu, 17 May 2012 18:03:54 +0200 |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20120428 Thunderbird/12.0.1 |
Hi,
this tool is what I used for testing. I ran it on the publicly available
SOA files (qx_{ann,cso,ins}.dat) and it doesn't find any discrepancies
(now -- after I fixed several bugs I probably wouldn't find without it).
It exhaustively tests every table by calling specific_values() for every
possible start and length in the allowed range; one file takes just a
few seconds to test. I didn't test values_elaborated(), because it's
generic and uses specific_values() data.
Usage: soa_stress_test ...list of dat files to test...
E.g.: ./soa_stress_test qx_{ann,cso,ins}.dat
Expected output:
$ ./soa_stress_test ../data/qx_ins.dat
Testing ../data/qx_ins.dat, 250
Testing ../data/qx_ins.dat, 251
Testing ../data/qx_ins.dat, 252
Testing ../data/qx_ins.dat, 300
...
Testing ../data/qx_ins.dat, 203
Testing ../data/qx_ins.dat, 202
$
The .dat files must have corresponding .xtable files generated first,
obviously.
Compilation of the tool requires LMI sources patched with the four
patches I posted. Then:
c++ -o soa_stress_test.exe \
soa_stress_test.cpp \
actuarial_table.cpp \
xml_lmi.cpp \
alert{,_cli}.cpp \
-lboost_{filesystem,system}-mt -lxmlwrapp -lncurses
(Same comment about makefiles applies.)
Regards,
Vaclav
---
soa_stress_test.cpp | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 131 insertions(+)
diff --git a/soa_stress_test.cpp b/soa_stress_test.cpp
new file mode 100644
index 0000000..19b4207
--- /dev/null
+++ b/soa_stress_test.cpp
@@ -0,0 +1,131 @@
+
+#include "soa_helpers.hpp"
+
+#include "actuarial_table.hpp"
+#include "assert_lmi.hpp"
+
+#include <cmath>
+#include <ios>
+#include <istream>
+
+inline bool almost_equal_doubles(double a, double b)
+{
+ return std::abs(a - b) < 0.00000001;
+}
+
+inline bool almost_equal_doubles(std::vector<double> const& a,
std::vector<double> const& b)
+{
+ if(a.size() != b.size())
+ return false;
+
+ size_t const size = a.size();
+ for(size_t i = 0; i < size; i++)
+ {
+ if(!almost_equal_doubles(a[i], b[i]))
+ return false;
+ }
+
+ return true;
+}
+
+void report_vector_difference
+ (int start
+ ,std::vector<double> const& data_xml
+ ,std::vector<double> const& data_soa
+ )
+{
+ std::cerr << boost::format("Results differ for %1% values starting at
%2%:")
+ % data_xml.size()
+ % start
+ << std::endl;
+
+ std::cerr << boost::format(" \t%|10|\t%|10|") % "xml" % "soa" <<
std::endl;
+ for(int i = 0; i < data_xml.size(); i++)
+ {
+ if(!almost_equal_doubles(data_xml[i], data_soa[i]))
+ {
+ std::cerr << boost::format("[%d]\t%|10|\t%|10|")
+ % i
+ % data_xml[i]
+ % data_soa[i]
+ << std::endl;
+ }
+ }
+ throw std::runtime_error("XML table data are incorrect");
+}
+
+
+void test_single_table(char const* filename, int index)
+{
+ soa_actuarial_table soa(filename, index);
+ actuarial_table xml(filename, index);
+
+ LMI_ASSERT( soa.table_type() == xml.table_type() );
+
+ if (xml.table_type() != e_table_duration)
+ {
+ LMI_ASSERT( soa.min_age() == xml.min_age() );
+ LMI_ASSERT( soa.max_age() == xml.max_age() );
+ }
+
+ if(xml.table_type() == e_table_select_and_ultimate)
+ {
+ LMI_ASSERT( soa.select_period() == xml.select_period() );
+ LMI_ASSERT( soa.max_select_age() == xml.max_select_age() );
+ }
+
+ for(int start = xml.min_age(); start < xml.max_age(); start++)
+ {
+ for(int length = 1; length <= xml.max_age() - start; length++)
+ {
+ std::vector<double> result_xml = xml.values(start, length);
+ std::vector<double> result_soa = soa.values(start, length);
+ LMI_ASSERT(result_xml.size() == length);
+ LMI_ASSERT(result_soa.size() == length);
+ if(!almost_equal_doubles(result_xml, result_soa))
+ report_vector_difference(start, result_xml, result_soa);
+ }
+ }
+}
+
+
+void stress_test(char const* filename)
+{
+ const std::vector<soa_record_info> tables = list_soa_file_tables(filename);
+
+ for(std::vector<soa_record_info>::const_iterator i = tables.begin()
+ ;i != tables.end()
+ ;++i)
+ {
+ try
+ {
+ std::cout << "Testing " << filename << ", " << i->index <<
std::endl;
+ test_single_table(filename, i->index);
+ }
+ catch(std::exception const& e)
+ {
+ error(boost::format("In file %1%, table %2%:\n%3%")
+ % filename
+ % i->index
+ % e.what());
+ }
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ try
+ {
+ for(int i = 1; i < argc; i++)
+ {
+ stress_test(argv[i]);
+ }
+ return 0;
+ }
+ catch ( const std::exception& e )
+ {
+ std::cerr << "Error:" << std::endl << e.what() << std::endl;
+ return 1;
+ }
+}
--
1.7.10.2
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi] test tool for validating actuarial_table implementations,
Vaclav Slavik <=