00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <cmath>
00019 #include <cstdlib>
00020 #include <fstream>
00021 #include <iostream>
00022 #include <string>
00023 #include <sstream>
00024
00025
00026
00027 #include "bounding_layer.h"
00028
00029
00030
00031 #include "../../parsers/tinyxml/tinyxml.h"
00032
00033 namespace OpenNN
00034 {
00035
00036
00037
00040
00041 BoundingLayer::BoundingLayer(void)
00042 {
00043 set();
00044 }
00045
00046
00047
00048
00052
00053 BoundingLayer::BoundingLayer(const unsigned int& bounding_neurons_number)
00054 {
00055 set(bounding_neurons_number);
00056
00057 set_default();
00058 }
00059
00060
00061
00062
00066
00067 BoundingLayer::BoundingLayer(TiXmlElement* bounding_layer_element)
00068 {
00069 set(bounding_layer_element);
00070 }
00071
00072
00073
00074
00078
00079 BoundingLayer::BoundingLayer(const BoundingLayer& other_bounding_layer)
00080 {
00081 set(other_bounding_layer);
00082 }
00083
00084
00085
00086
00089
00090 BoundingLayer::~BoundingLayer(void)
00091 {
00092 }
00093
00094
00095
00096
00100
00101 BoundingLayer& BoundingLayer::operator = (const BoundingLayer& other_bounding_layer)
00102 {
00103 if(this != &other_bounding_layer)
00104 {
00105 lower_bounds = other_bounding_layer.lower_bounds;
00106 upper_bounds = other_bounding_layer.upper_bounds;
00107 display = other_bounding_layer.display;
00108 }
00109
00110 return(*this);
00111 }
00112
00113
00114
00115
00116
00117
00122
00123 bool BoundingLayer::operator == (const BoundingLayer& other_bounding_layer) const
00124 {
00125 if(lower_bounds == other_bounding_layer.lower_bounds
00126 && upper_bounds == other_bounding_layer.upper_bounds
00127 && display == other_bounding_layer.display)
00128 {
00129 return(true);
00130 }
00131 else
00132 {
00133 return(false);
00134 }
00135 }
00136
00137
00138
00139
00141
00142 bool BoundingLayer::is_empty(void) const
00143 {
00144 if(count_bounding_neurons_number() == 0)
00145 {
00146 return(true);
00147 }
00148 else
00149 {
00150 return(false);
00151 }
00152 }
00153
00154
00155
00156
00158
00159 unsigned int BoundingLayer::count_bounding_neurons_number(void) const
00160 {
00161 return(lower_bounds.size());
00162 }
00163
00164
00165
00166
00168
00169 const Vector<double>& BoundingLayer::get_lower_bounds(void) const
00170 {
00171 return(lower_bounds);
00172 }
00173
00174
00175
00176
00179
00180 double BoundingLayer::get_lower_bound(const unsigned int& i) const
00181 {
00182
00183
00184 #ifdef _DEBUG
00185
00186 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00187
00188 if(i >= bounding_neurons_number)
00189 {
00190 std::ostringstream buffer;
00191
00192 buffer << "OpenNN Exception: BoundingLayer class.\n"
00193 << "double get_lower_bound(const unsigned int&) const method.\n"
00194 << "Index must be less than number of bounding neurons.\n";
00195
00196 throw std::logic_error(buffer.str());
00197 }
00198
00199 #endif
00200
00201 return(lower_bounds[i]);
00202 }
00203
00204
00205
00206
00208
00209 const Vector<double>& BoundingLayer::get_upper_bounds(void) const
00210 {
00211 return(upper_bounds);
00212 }
00213
00214
00215
00216
00219
00220 double BoundingLayer::get_upper_bound(const unsigned int& i) const
00221 {
00222
00223
00224 #ifdef _DEBUG
00225
00226 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00227
00228 if(bounding_neurons_number == 0)
00229 {
00230 std::ostringstream buffer;
00231
00232 buffer << "OpenNN Exception: BoundingLayer class.\n"
00233 << "double get_upper_bound(const unsigned int&) const method.\n"
00234 << "Number of bounding neurons is zero.\n";
00235
00236 throw std::logic_error(buffer.str());
00237 }
00238 else if(i >= bounding_neurons_number)
00239 {
00240 std::ostringstream buffer;
00241
00242 buffer << "OpenNN Exception: BoundingLayer class.\n"
00243 << "double get_upper_bound(const unsigned int&) const method.\n"
00244 << "Index must be less than number of bounding neurons.\n";
00245
00246 throw std::logic_error(buffer.str());
00247 }
00248
00249 #endif
00250
00251 return(upper_bounds[i]);
00252 }
00253
00254
00255
00256
00261
00262 Vector< Vector<double>* > BoundingLayer::get_bounds(void)
00263 {
00264 Vector< Vector<double>* > bounds(2);
00265
00266 bounds[0] = &lower_bounds;
00267 bounds[1] = &upper_bounds;
00268
00269 return(bounds);
00270 }
00271
00272
00273
00274
00277
00278 void BoundingLayer::set(void)
00279 {
00280 lower_bounds.set();
00281 upper_bounds.set();
00282
00283 set_default();
00284 }
00285
00286
00287
00288
00292
00293 void BoundingLayer::set(const unsigned int& new_bounding_neurons_number)
00294 {
00295 lower_bounds.set(new_bounding_neurons_number);
00296 upper_bounds.set(new_bounding_neurons_number);
00297
00298 set_default();
00299 }
00300
00301
00302
00303
00306
00307 void BoundingLayer::set(TiXmlElement* bounding_layer_element)
00308 {
00309 from_XML(bounding_layer_element);
00310 }
00311
00312
00313
00314
00317
00318 void BoundingLayer::set(const BoundingLayer& other_bounding_layer)
00319 {
00320 lower_bounds = other_bounding_layer.lower_bounds;
00321
00322 upper_bounds = other_bounding_layer.upper_bounds;
00323
00324 display = other_bounding_layer.display;
00325 }
00326
00327
00328
00329
00332
00333 void BoundingLayer::set_lower_bounds(const Vector<double>& new_lower_bounds)
00334 {
00335
00336
00337 #ifdef _DEBUG
00338
00339 unsigned int bounding_neurons_number = count_bounding_neurons_number();
00340
00341 if(new_lower_bounds.size() != bounding_neurons_number)
00342 {
00343 std::ostringstream buffer;
00344
00345 buffer << "OpenNN Exception: BoundingLayer class.\n"
00346 << "void set_lower_bounds(const Vector<double>&) method.\n"
00347 << "Size must be equal to number of bounding neurons number.\n";
00348
00349 throw std::logic_error(buffer.str());
00350 }
00351
00352 #endif
00353
00354
00355
00356 lower_bounds = new_lower_bounds;
00357 }
00358
00359
00360
00361
00366
00367 void BoundingLayer::set_lower_bound(const unsigned int& index, const double& new_lower_bound)
00368 {
00369 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00370
00371
00372
00373 #ifdef _DEBUG
00374
00375 if(index >= bounding_neurons_number)
00376 {
00377 std::ostringstream buffer;
00378
00379 buffer << "OpenNN Exception: BoundingLayer class.\n"
00380 << "void set_lower_bound(const unsigned int&, const double&) method.\n"
00381 << "Index of bounding neurons must be less than number of bounding neurons.\n";
00382
00383 throw std::logic_error(buffer.str());
00384 }
00385
00386 #endif
00387
00388 if(lower_bounds.size() != bounding_neurons_number)
00389 {
00390 lower_bounds.set(bounding_neurons_number, -1.0e99);
00391 }
00392
00393
00394
00395 lower_bounds[index] = new_lower_bound;
00396 }
00397
00398
00399
00400
00404
00405 void BoundingLayer::set_upper_bounds(const Vector<double>& new_upper_bounds)
00406 {
00407
00408
00409 #ifdef _DEBUG
00410
00411 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00412
00413 if(new_upper_bounds.size() != bounding_neurons_number)
00414 {
00415 std::ostringstream buffer;
00416
00417 buffer << "OpenNN Exception: BoundingLayer class.\n"
00418 << "void set_upper_bound(const Vector<double>&) method.\n"
00419 << "Size must be equal to number of bounding neurons.\n";
00420
00421 throw std::logic_error(buffer.str());
00422 }
00423
00424 #endif
00425
00426
00427
00428 upper_bounds = new_upper_bounds;
00429 }
00430
00431
00432
00433
00438
00439 void BoundingLayer::set_upper_bound(const unsigned int& index, const double& new_upper_bound)
00440 {
00441 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00442
00443
00444
00445 #ifdef _DEBUG
00446
00447 if(index >= bounding_neurons_number)
00448 {
00449 std::ostringstream buffer;
00450
00451 buffer << "OpenNN Exception: BoundingLayer class.\n"
00452 << "void set_upper_bound(const unsigned int&, const double&) method.\n"
00453 << "Index of bounding neuron must be less than number of bounding neurons.\n";
00454
00455 throw std::logic_error(buffer.str());
00456 }
00457
00458 #endif
00459
00460 if(upper_bounds.size() != bounding_neurons_number)
00461 {
00462 upper_bounds.set(bounding_neurons_number, 1.0e99);
00463 }
00464
00465
00466
00467 upper_bounds[index] = new_upper_bound;
00468 }
00469
00470
00471
00472
00479
00480 void BoundingLayer::set_bounds(const Vector< Vector<double> >& new_bounds)
00481 {
00482
00483
00484 #ifdef _DEBUG
00485
00486 const unsigned int size = new_bounds.size();
00487
00488 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00489
00490 if(size != 2)
00491 {
00492 std::ostringstream buffer;
00493
00494 buffer << "OpenNN Exception: BoundingLayer class.\n"
00495 << "void set_bounds(const Vector< Vector<double> >&) method.\n"
00496 << "Number of rows must be 2.\n";
00497
00498 throw std::logic_error(buffer.str());
00499 }
00500 else if(new_bounds[0].size() != bounding_neurons_number
00501 && new_bounds[1].size() != bounding_neurons_number)
00502 {
00503 std::ostringstream buffer;
00504
00505 buffer << "OpenNN Exception: BoundingLayer class.\n"
00506 << "void set_bounds(const Vector< Vector<double> >&) method.\n"
00507 << "Number of columns must be equal to number of bounding neurons.\n";
00508
00509 throw std::logic_error(buffer.str());
00510 }
00511
00512 #endif
00513
00514
00515
00516 set_lower_bounds(new_bounds[0]);
00517 set_upper_bounds(new_bounds[1]);
00518 }
00519
00520
00521
00522
00527
00528 void BoundingLayer::set_display(const bool& new_display)
00529 {
00530 display = new_display;
00531 }
00532
00533
00534
00535
00540
00541 void BoundingLayer::set_default(void)
00542 {
00543 display = true;
00544 }
00545
00546
00547
00548
00550
00551 void BoundingLayer::initialize_random(void)
00552 {
00553
00554 }
00555
00556
00557
00558
00561
00562 Vector<double> BoundingLayer::calculate_outputs(const Vector<double>& inputs) const
00563 {
00564
00565
00566 #ifdef _DEBUG
00567
00568 const unsigned int inputs_size = inputs.size();
00569
00570 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00571
00572 if(inputs_size != bounding_neurons_number)
00573 {
00574 std::ostringstream buffer;
00575
00576 buffer << "OpenNN Exception: BoundingLayer class.\n"
00577 << "Vector<double> calculate_outputs(const Vector<double>&) const method.\n"
00578 << "Size of inputs must be equal to number of bounding neurons.\n";
00579
00580 throw std::logic_error(buffer.str());
00581 }
00582
00583 #endif
00584
00585 return(inputs.calculate_lower_upper_bounded(lower_bounds, upper_bounds));
00586 }
00587
00588
00589
00590
00593
00594 Vector<double> BoundingLayer::calculate_derivative(const Vector<double>& inputs) const
00595 {
00596 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00597
00598 const Vector<double> outputs = calculate_outputs(inputs);
00599
00600 Vector<double> derivatives(bounding_neurons_number);
00601
00602 for(unsigned int i = 0; i < bounding_neurons_number; i++)
00603 {
00604 if(outputs[i] <= lower_bounds[i] || outputs[i] >= upper_bounds[i])
00605 {
00606 derivatives[i] = 0.0;
00607 }
00608 else
00609 {
00610 derivatives[i] = 1.0;
00611 }
00612 }
00613
00614 return(derivatives);
00615 }
00616
00617
00618
00619
00622
00623 Vector<double> BoundingLayer::calculate_second_derivative(const Vector<double>& inputs) const
00624 {
00625 std::ostringstream buffer;
00626
00627 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00628
00629 const Vector<double> outputs = calculate_outputs(inputs);
00630
00631 for(unsigned int i = 0; i < bounding_neurons_number; i++)
00632 {
00633 if(outputs[i] == lower_bounds[i])
00634 {
00635 buffer << "OpenNN Exception: BoundingLayer class.\n"
00636 << "Vector<double> calculate_outputs(const Vector<double>&) const method.\n"
00637 << "Output is equal to lower bound. The bounding function is not differentiable at this point.\n";
00638
00639 throw std::logic_error(buffer.str());
00640 }
00641 else if(outputs[i] == upper_bounds[i])
00642 {
00643 buffer << "OpenNN Exception: BoundingLayer class.\n"
00644 << "Vector<double> calculate_outputs(const Vector<double>&) const method.\n"
00645 << "Output is equal to upper bound. The bounding function is not differentiable at this point.\n";
00646
00647 throw std::logic_error(buffer.str());
00648 }
00649 }
00650
00651 Vector<double> second_derivative(bounding_neurons_number, 0.0);
00652
00653 return(second_derivative);
00654 }
00655
00656
00657
00658
00662
00663 Matrix<double> BoundingLayer::arrange_Jacobian(const Vector<double>& derivatives) const
00664 {
00665 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00666
00667
00668
00669 #ifdef _DEBUG
00670
00671 const unsigned int derivatives_size = derivatives.size();
00672
00673 if(derivatives_size != bounding_neurons_number)
00674 {
00675 std::ostringstream buffer;
00676
00677 buffer << "OpenNN Exception: BoundingLayer class.\n"
00678 << "Matrix<double> arrange_Jacobian(const Vector<double>&) method.\n"
00679 << "Size of derivatives must be equal to number of bounding neurons.\n";
00680
00681 throw std::logic_error(buffer.str());
00682 }
00683
00684 #endif
00685
00686 Matrix<double> Jacobian(bounding_neurons_number, bounding_neurons_number, 0.0);
00687 Jacobian.set_diagonal(derivatives);
00688
00689 return(Jacobian);
00690 }
00691
00692
00693
00694
00697
00698 Vector< Matrix<double> > BoundingLayer::arrange_Hessian_form(const Vector<double>&) const
00699 {
00700 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00701
00702 Vector< Matrix<double> > bounded_Hessian_form(bounding_neurons_number);
00703
00704 for(unsigned int i = 0; i < bounding_neurons_number; i++)
00705 {
00706 bounded_Hessian_form[i].set(bounding_neurons_number, bounding_neurons_number, 0.0);
00707 }
00708
00709 return(bounded_Hessian_form);
00710 }
00711
00712
00713
00714
00716
00717 std::string BoundingLayer::write_expression(const Vector<std::string>& inputs_name, const Vector<std::string>& outputs_name) const
00718 {
00719 std::stringstream expression;
00720
00721 const unsigned int bounding_neurons_number = count_bounding_neurons_number();
00722
00723 for(unsigned int i = 0; i < bounding_neurons_number; i++)
00724 {
00725 expression << outputs_name[i] << " < " << lower_bounds[i] << " ? " << lower_bounds[i] << " : " << inputs_name[i] << "\n";
00726 expression << outputs_name[i] << " > " << upper_bounds[i] << " ? " << upper_bounds[i] << " : " << inputs_name[i] << "\n";
00727 }
00728
00729 return(expression.str());
00730 }
00731
00732
00733
00734
00736
00737 std::string BoundingLayer::to_string(void) const
00738 {
00739 std::ostringstream buffer;
00740
00741 buffer << "Bounding layer\n"
00742 << "Lower bounds: " << lower_bounds << "\n"
00743 << "Upper bounds: " << upper_bounds << "\n"
00744 << "Display: " << display << "\n";
00745
00746 return(buffer.str());
00747 }
00748
00749
00750
00751
00754
00755 TiXmlElement* BoundingLayer::to_XML(void) const
00756 {
00757 std::ostringstream buffer;
00758
00759 TiXmlElement* bounding_layer_element = new TiXmlElement("BoundingLayer");
00760 bounding_layer_element->SetAttribute("Version", 4);
00761
00762
00763
00764 {
00765 TiXmlElement* element = new TiXmlElement("LowerBounds");
00766 bounding_layer_element->LinkEndChild(element);
00767
00768 buffer.str("");
00769 buffer << lower_bounds;
00770
00771 TiXmlText* text = new TiXmlText(buffer.str().c_str());
00772 element->LinkEndChild(text);
00773 }
00774
00775
00776
00777 {
00778 TiXmlElement* element = new TiXmlElement("UpperBounds");
00779 bounding_layer_element->LinkEndChild(element);
00780
00781 buffer.str("");
00782 buffer << upper_bounds;
00783
00784 TiXmlText* text = new TiXmlText(buffer.str().c_str());
00785 element->LinkEndChild(text);
00786 }
00787
00788
00789
00790 {
00791 TiXmlElement* display_element = new TiXmlElement("Display");
00792 bounding_layer_element->LinkEndChild(display_element);
00793
00794 buffer.str("");
00795 buffer << display;
00796
00797 TiXmlText* display_text = new TiXmlText(buffer.str().c_str());
00798 display_element->LinkEndChild(display_text);
00799 }
00800
00801 return(bounding_layer_element);
00802 }
00803
00804
00805
00806
00809
00810 void BoundingLayer::from_XML(TiXmlElement* bounding_layer_element)
00811 {
00812 if(bounding_layer_element)
00813 {
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 {
00835 TiXmlElement* lower_bounds_element = bounding_layer_element->FirstChildElement("LowerBounds");
00836
00837 if(lower_bounds_element)
00838 {
00839 const char* lower_bounds_text = lower_bounds_element->GetText();
00840
00841 if(lower_bounds_text)
00842 {
00843 Vector<double> new_lower_bounds;
00844 new_lower_bounds.parse(lower_bounds_text);
00845
00846 try
00847 {
00848 set_lower_bounds(new_lower_bounds);
00849 }
00850 catch(std::exception& e)
00851 {
00852 std::cout << e.what() << std::endl;
00853 }
00854 }
00855 }
00856 }
00857
00858
00859 {
00860 TiXmlElement* upper_bounds_element = bounding_layer_element->FirstChildElement("UpperBounds");
00861
00862 if(upper_bounds_element)
00863 {
00864 const char* upper_bounds_text = upper_bounds_element->GetText();
00865
00866 if(upper_bounds_text)
00867 {
00868 Vector<double> new_upper_bounds;
00869 new_upper_bounds.parse(upper_bounds_text);
00870
00871 try
00872 {
00873 set_upper_bounds(new_upper_bounds);
00874 }
00875 catch(std::exception& e)
00876 {
00877 std::cout << e.what() << std::endl;
00878 }
00879 }
00880 }
00881 }
00882
00883
00884 {
00885 TiXmlElement* display_element = bounding_layer_element->FirstChildElement("Display");
00886
00887 if(display)
00888 {
00889 std::string new_display_string = display_element->GetText();
00890
00891 try
00892 {
00893 set_display(new_display_string != "0");
00894 }
00895 catch(std::exception& e)
00896 {
00897 std::cout << e.what() << std::endl;
00898 }
00899 }
00900 }
00901 }
00902 }
00903
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921