00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "NewtonMethod.h"
00014
00015 #include <iostream>
00016 #include <fstream>
00017 #include <stdlib.h>
00018 #include <math.h>
00019 #include <time.h>
00020
00021 namespace Purple
00022 {
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 NewtonMethod::NewtonMethod(ObjectiveFunction* newObjectiveFunction)
00051 : OptimizationAlgorithm(newObjectiveFunction)
00052 {
00053
00054
00055 int numberOfVariables = objectiveFunction->getNumberOfVariables();
00056
00057 Vector<double> lowerBound = objectiveFunction->getLowerBound();
00058 Vector<double> upperBound = objectiveFunction->getUpperBound();
00059
00060 Vector<double> newInitialArgument(numberOfVariables, 0.0);
00061
00062 for(int i = 0; i < numberOfVariables; i++)
00063 {
00064 double random = (double)rand()/(RAND_MAX+1.0);
00065
00066 newInitialArgument[i]
00067 = lowerBound[i] + (upperBound[i] - lowerBound[i])*random;
00068 }
00069
00070 initialArgument = newInitialArgument;
00071
00072
00073
00074 evaluationGoal = 0.0;
00075 gradientNormGoal = 0.0;
00076 maximumTime = 1.0e6;
00077 maximumNumberOfIterations = 100;
00078
00079
00080
00081 showPeriod = 25;
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 NewtonMethod::NewtonMethod(void) : OptimizationAlgorithm()
00107 {
00108
00109
00110 evaluationGoal = 0.0;
00111 gradientNormGoal = 0.0;
00112 maximumTime = 1.0e6;
00113 maximumNumberOfIterations = 100;
00114
00115
00116
00117 showPeriod = 25;
00118 }
00119
00120
00121
00122
00123
00124
00125 NewtonMethod::~NewtonMethod(void)
00126 {
00127
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 Vector<double> NewtonMethod::getInitialArgument(void)
00140 {
00141 return(initialArgument);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151 double NewtonMethod::getGradientNormGoal(void)
00152 {
00153 return(gradientNormGoal);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163 int NewtonMethod::getMaximumNumberOfIterations(void)
00164 {
00165 return(maximumNumberOfIterations);
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 int NewtonMethod::getShowPeriod(void)
00175 {
00176 return(showPeriod);
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 void NewtonMethod::setInitialArgument(Vector<double> newInitialArgument)
00188 {
00189 int size = newInitialArgument.getSize();
00190
00191 int numberOfVariables = objectiveFunction->getNumberOfVariables();
00192
00193 if(size != numberOfVariables)
00194 {
00195 std::cout << std::endl
00196 << "Error: NewtonMethod class. "
00197 << "double setInitialArgument(Vector<double>) method." << std::endl
00198 << "Size of initial argument must be equal to number of variables."
00199 << std::endl << std::endl;
00200
00201 exit(1);
00202 }
00203
00204
00205 initialArgument = newInitialArgument;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 void NewtonMethod::setGradientNormGoal(double newGradientNormGoal)
00219 {
00220 if(gradientNormGoal < 0.0)
00221 {
00222 std::cout << std::endl
00223 << "Error: NewtonMethod class." << std::endl
00224 << "void setGradientNormGoal(double) method."
00225 << std::endl
00226 << "Gradient norm goal must be equal or greater than 0."
00227 << std::endl << std::endl;
00228 exit(1);
00229 }
00230
00231
00232
00233 gradientNormGoal = newGradientNormGoal;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 void NewtonMethod
00245 ::setMaximumNumberOfIterations(int newMaximumNumberOfIterations)
00246 {
00247 if(newMaximumNumberOfIterations <= 0)
00248 {
00249 std::cout << std::endl
00250 << "Error: NewtonMethod class." << std::endl
00251 << "void setMaximumNumberOfIterations(int) method."
00252 << std::endl
00253 << "Maximum number of iterations must be greater than 0."
00254 << std::endl
00255 << std::endl;
00256
00257 exit(1);
00258 }
00259
00260
00261
00262 maximumNumberOfIterations = newMaximumNumberOfIterations;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 void NewtonMethod::setShowPeriod(int newShowPeriod)
00275 {
00276 if(newShowPeriod <= 0)
00277 {
00278 std::cout << std::endl
00279 << "Error: NewtonMethod class." << std::endl
00280 << "void setShowPeriod(int) method."
00281 << std::endl
00282 << "Show period must be greater than 0."
00283 << std::endl << std::endl;
00284
00285 exit(1);
00286 }
00287
00288
00289
00290 showPeriod = newShowPeriod;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 Vector<double> NewtonMethod::getMinimalArgument(void)
00302 {
00303 int numberOfVariables = objectiveFunction->getNumberOfVariables();
00304
00305 Vector<double> minimalArgument(numberOfVariables, 0.0);
00306 Vector<double> argument(numberOfVariables, 0.0);
00307
00308
00309
00310 Vector<double> newEvaluationHistory(maximumNumberOfIterations+1, 0.0);
00311
00312 evaluationHistory = newEvaluationHistory;
00313
00314
00315
00316 Vector<double> newGradientNormHistory(maximumNumberOfIterations+1, 0.0);
00317
00318 gradientNormHistory = newGradientNormHistory;
00319
00320 double evaluation = 0.0;
00321
00322 Vector<double> gradient(numberOfVariables, 0.0);
00323
00324 double gradientNorm = 0.0;
00325
00326 Matrix<double> hessian(numberOfVariables, numberOfVariables, 0.0);
00327 Matrix<double> inverseHessian(numberOfVariables, numberOfVariables, 0.0);
00328 Vector<double> inverseHessianGradientProduct(numberOfVariables, 0.0);
00329
00330 time_t beginningTime, currentTime;
00331
00332 double elapsedTime = 0.0;
00333
00334
00335
00336 time(&beginningTime);
00337
00338
00339
00340 std::cout << std::endl
00341 << "Getting minimal argument with Newton's method..."
00342 << std::endl;
00343
00344 argument = initialArgument;
00345
00346
00347
00348 evaluation = objectiveFunction->getEvaluation(argument);
00349
00350 evaluationHistory[0] = evaluation;
00351
00352 if(evaluation <= evaluationGoal)
00353 {
00354 std::cout << std::endl
00355 << "Initial evaluation is less than goal." << std::endl
00356 << "Initial evaluation: " << evaluation << std::endl;
00357
00358 minimalArgument = argument;
00359
00360
00361
00362 std::cout << std::endl
00363 << "Minimal argument:" << std::endl;
00364
00365 for(int i = 0; i < numberOfVariables; i++)
00366 {
00367 std::cout << minimalArgument[i] << " ";
00368 }
00369
00370 return(minimalArgument);
00371 }
00372 else
00373 {
00374 std::cout << "Initial evaluation: " << evaluation << std::endl;
00375 }
00376
00377
00378
00379 gradient = objectiveFunction->getGradient(argument);
00380
00381 gradientNorm = objectiveFunction->getGradientNorm(gradient);
00382
00383 gradientNormHistory[0] = gradientNorm;
00384
00385 if(gradientNorm <= gradientNormGoal)
00386 {
00387 std::cout << std::endl
00388 << "Initial gradient norm is less than goal." << std::endl
00389 << "Initial gradient norm: " << gradientNorm << std::endl;
00390
00391 minimalArgument = argument;
00392
00393
00394
00395 std::cout << std::endl
00396 << "Minimal argument:" << std::endl;
00397
00398 for(int i = 0; i < numberOfVariables; i++)
00399 {
00400 std::cout << minimalArgument[i] << " ";
00401 }
00402
00403 return(minimalArgument);
00404 }
00405 else
00406 {
00407 std::cout << "Initial gradient norm: " << gradientNorm << std::endl;
00408 }
00409
00410
00411
00412 for(int iteration = 1; iteration <= maximumNumberOfIterations; iteration++)
00413 {
00414
00415
00416 inverseHessian = objectiveFunction->getInverseHessian(argument);
00417
00418
00419
00420 for(int i = 0; i < numberOfVariables; i++)
00421 {
00422 for(int j = 0; j < numberOfVariables; j++)
00423 {
00424 inverseHessianGradientProduct[i] += inverseHessian[i][j]*gradient[j];
00425 }
00426 }
00427
00428
00429
00430 for (int i = 0; i < numberOfVariables; i++)
00431 {
00432 argument[i] -= inverseHessianGradientProduct[i];
00433 }
00434
00435
00436
00437
00438 evaluation = objectiveFunction->getEvaluation(argument);
00439
00440 evaluationHistory[iteration] = evaluation;
00441
00442
00443
00444 gradient = objectiveFunction->getGradient(argument);
00445
00446 gradientNorm = objectiveFunction->getGradientNorm(gradient);
00447
00448 gradientNormHistory[iteration] = gradientNorm;
00449
00450
00451
00452
00453
00454
00455 if (evaluation <= evaluationGoal)
00456 {
00457 std::cout << std::endl
00458 << "Iteration " << iteration << ": "
00459 << "Evaluation goal reached." << std::endl;
00460
00461 std::cout << "Evaluation: " << evaluation << std::endl;
00462 std::cout << "Gradient norm: " << gradientNorm << std::endl;
00463
00464 break;
00465 }
00466
00467
00468
00469 if (gradientNorm <= gradientNormGoal)
00470 {
00471 std::cout << std::endl
00472 << "Iteration " << iteration << ": "
00473 << "Gradient norm goal reached."
00474 << std::endl;
00475
00476 std::cout << "Evaluation: " << evaluation << ";" << std::endl;
00477 std::cout << "Gradient norm: " << gradientNorm << ";" << std::endl;
00478
00479 break;
00480 }
00481
00482
00483
00484 time(¤tTime);
00485
00486 elapsedTime = difftime(currentTime, beginningTime);
00487
00488 if (elapsedTime >= maximumTime)
00489 {
00490 std::cout << std::endl
00491 << "Iteration " << iteration << ": "
00492 << "Maximum optimization time reached."
00493 << std::endl;
00494
00495 std::cout << "Evaluation: " << evaluation << ";" << std::endl;
00496 std::cout << "Gradient norm: " << gradientNorm << ";" << std::endl;
00497
00498 break;
00499 }
00500
00501
00502
00503 if (iteration == maximumNumberOfIterations)
00504 {
00505 std::cout << std::endl
00506 << "Iteration " << iteration << ": "
00507 << "Maximum number of iterations reached."
00508 << std::endl;
00509
00510 std::cout << "Evaluation: " << evaluation << std::endl;
00511 std::cout << "Gradient norm: " << gradientNorm << std::endl;
00512
00513 break;
00514 }
00515
00516
00517
00518 if(iteration % showPeriod == 0)
00519 {
00520 std::cout << std::endl
00521 << "Iteration " << iteration << "; " << std::endl;
00522
00523 std::cout << "Evaluation: " << evaluation << ";" << std::endl;
00524 std::cout << "Gradient norm: " << gradientNorm << ";" << std::endl;
00525 }
00526 }
00527
00528
00529
00530 minimalArgument = argument;
00531
00532
00533
00534 std::cout << std::endl
00535 << "Minimal argument:" << std::endl;
00536
00537 for(int i = 0; i < numberOfVariables; i++)
00538 {
00539 std::cout << minimalArgument[i] << " ";
00540 }
00541
00542 std::cout << std::endl;
00543
00544 return(minimalArgument);
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 void NewtonMethod::print(void)
00569 {
00570 std::cout << std::endl
00571 << "Newton's Method Object." << std::endl;
00572
00573 int numberOfVariables = objectiveFunction->getNumberOfVariables();
00574
00575
00576
00577 std::cout << std::endl
00578 << "Initial argument:" << std::endl;
00579
00580 for(int i = 0; i < numberOfVariables; i++)
00581 {
00582 std::cout << initialArgument[i] << " ";
00583 }
00584
00585 std::cout << std::endl;
00586
00587
00588
00589 std::cout << std::endl
00590 << "Stopping criteria: " << std::endl
00591 << "Evaluation goal: " << std::endl
00592 << evaluationGoal << std::endl
00593 << "Gradient norm goal" << std::endl
00594 << gradientNormGoal <<std::endl
00595 << "Maximum time: " << std::endl
00596 << maximumTime << std::endl
00597 << "Maximum number of iterations: " << std::endl
00598 << maximumNumberOfIterations << std::endl;
00599
00600
00601
00602 std::cout << std::endl
00603 << "User stuff: " << std::endl
00604 << "Show period: " << std::endl
00605 << showPeriod
00606 << std::endl;
00607
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 void NewtonMethod::save(char* filename)
00635 {
00636
00637
00638 std::fstream file;
00639
00640 file.open(filename, std::ios::out);
00641
00642 if(!file.is_open())
00643 {
00644 std::cout << std::endl
00645 << "Error: NewtonMethod class." << std::endl
00646 << "void save(char*) method."
00647 << std::endl
00648 << "Cannot open Newton method object data file." << std::endl
00649 << std::endl;
00650
00651 exit(1);
00652 }
00653 else
00654 {
00655 std::cout << std::endl
00656 << "Saving Newton method object to data file..." << std::endl;
00657 }
00658
00659
00660
00661 file << "% Purple: An Open Source Numerical Optimization C++ Library."
00662 << std::endl
00663 << "% Newton Method Object." << std::endl;
00664
00665 int numberOfVariables = objectiveFunction->getNumberOfVariables();
00666
00667
00668
00669 file << "InitialArgument:" << std::endl;
00670
00671 for(int i = 0; i < numberOfVariables; i++)
00672 {
00673 file << initialArgument[i] << " ";
00674 }
00675
00676 file << std::endl;
00677
00678
00679
00680 file << "EvaluationGoal:" << std::endl
00681 << evaluationGoal << std::endl
00682 << "GradientNormGoal:" << std::endl
00683 << gradientNormGoal << std::endl
00684 << "MaximumTime: " << std::endl
00685 << maximumTime << std::endl
00686 << "MaximumNumberOfIterations: " << std::endl
00687 << maximumNumberOfIterations << std::endl;
00688
00689
00690
00691 file << "ShowPeriod: " << std::endl
00692 << showPeriod << std::endl;
00693
00694 file.close();
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 void NewtonMethod::load(char* filename)
00724 {
00725
00726
00727 std::fstream file;
00728
00729 file.open(filename, std::ios::in);
00730
00731 if(!file.is_open())
00732 {
00733 std::cout << std::endl
00734 << "Error: NewtonMethod class." << std::endl
00735 << "void load(char*) method."
00736 << std::endl
00737 << "Cannot open Newton method object data file." << std::endl;
00738
00739 exit(1);
00740 }
00741 else
00742 {
00743 std::cout << std::endl
00744 << "Loading Newton method object from data file..."
00745 << std::endl;
00746 }
00747
00748 std::string word;
00749
00750
00751
00752 while(word != "InitialArgument:")
00753 {
00754 file >> word;
00755 }
00756
00757 int numberOfVariables = objectiveFunction->getNumberOfVariables();
00758
00759 for(int i = 0; i < numberOfVariables; i++)
00760 {
00761 file >> initialArgument[i];
00762 }
00763
00764
00765
00766
00767
00768 file >> word;
00769
00770 file >> evaluationGoal;
00771
00772
00773
00774 file >> word;
00775
00776 file >> gradientNormGoal;
00777
00778
00779
00780 file >> word;
00781
00782 file >> maximumTime;
00783
00784
00785
00786 file >> word;
00787
00788 file >> maximumNumberOfIterations;
00789
00790
00791
00792
00793
00794 file >> word;
00795
00796 file >> showPeriod;
00797
00798
00799
00800 file.close();
00801 }
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816 void NewtonMethod::saveOptimizationHistory(char* filename)
00817 {
00818 std::fstream file;
00819
00820 file.open(filename, std::ios::out);
00821
00822
00823
00824 if(!file.is_open())
00825 {
00826 std::cout << std::endl
00827 << "Error: NewtonMethod class. " << std::endl
00828 << "void saveOptimizationHistory(char*) method."
00829 << std::endl
00830 << "Cannot open optimization history data file." << std::endl
00831 << std::endl;
00832
00833 exit(1);
00834 }
00835 else
00836 {
00837 std::cout << std::endl
00838 << "Saving optimization history to data file..." << std::endl;
00839 }
00840
00841
00842
00843 file << "% Purple: An Open Source Numerical Optimization C++ Library."
00844 << std::endl
00845 << "% Newton Method Optimization History." << std::endl
00846 << "% 1 - Iteration." << std::endl
00847 << "% 2 - Objective function evaluation." << std::endl
00848 << "% 3 - Objective function gradient norm." << std::endl;
00849
00850
00851
00852 int size = evaluationHistory.getSize();
00853
00854 for (int i = 0; i < size; i++)
00855 {
00856 file << i << " "
00857 << evaluationHistory[i] << " "
00858 << gradientNormHistory[i] << std::endl;
00859 }
00860
00861 file << std::endl;
00862
00863 file.close();
00864 }
00865
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884