00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ObjectiveFunction.h"
00015
00016 #include<iostream>
00017 #include <math.h>
00018 #include <sstream>
00019 #include <stdexcept>
00020
00021 namespace Purple
00022 {
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 ObjectiveFunction::ObjectiveFunction(void)
00035 {
00036 numberOfEvaluations = 0;
00037
00038 epsilon = 1.0e-6;
00039 }
00040
00041
00042
00043
00044
00045
00046 ObjectiveFunction::~ObjectiveFunction(void)
00047 {
00048
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058 int ObjectiveFunction::getNumberOfVariables(void)
00059 {
00060 return(numberOfVariables);
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 Vector<double> ObjectiveFunction::getLowerBound(void)
00072 {
00073 return(lowerBound);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083 Vector<double> ObjectiveFunction::getUpperBound(void)
00084 {
00085 return(upperBound);
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 Matrix<double> ObjectiveFunction::getDomain(void)
00098 {
00099 Matrix<double> domain(2, numberOfVariables, 0.0);
00100
00101 for(int i = 0; i< numberOfVariables; i++)
00102 {
00103 domain[0][i] = lowerBound[i];
00104 domain[1][i] = upperBound[i];
00105 }
00106
00107 return(domain);
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 double ObjectiveFunction::getEpsilon(void)
00120 {
00121 return(epsilon);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 int ObjectiveFunction::getNumberOfEvaluations(void)
00133 {
00134 return(numberOfEvaluations);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144 void ObjectiveFunction::setNumberOfVariables(int newNumberOfVariables)
00145 {
00146 if(newNumberOfVariables < 0)
00147 {
00148 std::cout << std::endl
00149 << "Error: ObjectiveFunction class. "
00150 << "void setNumberOfVariables(int) method."
00151 << std::endl
00152 << "Number of variables must be equal or greater than zero."
00153 << std::endl
00154 << std::endl;
00155
00156 exit(1);
00157 }
00158
00159 numberOfVariables = newNumberOfVariables;
00160
00161
00162
00163 Vector<double> newLowerBound(numberOfVariables, -1.0);
00164
00165 lowerBound = newLowerBound;
00166
00167
00168
00169 Vector<double> newUpperBound(numberOfVariables, 1.0);
00170
00171 upperBound = newUpperBound;
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 void ObjectiveFunction::setLowerBound(Vector<double> newLowerBound)
00185 {
00186 if(newLowerBound.getSize() != numberOfVariables)
00187 {
00188 std::cout << std::endl
00189 << "Error: ObjectiveFunction class. "
00190 << "void setLowerBound(Vector<double>) method."
00191 << std::endl
00192 << "Size must be equal to number of variables." << std::endl
00193 << std::endl;
00194
00195 exit(1);
00196 }
00197 else
00198 {
00199
00200
00201 for(int i = 0; i < numberOfVariables; i++)
00202 {
00203 if(newLowerBound[i] > upperBound[i])
00204 {
00205 std::cout << std::endl
00206 << "Error: ObjectiveFunction class. "
00207 << "void setLowerBound(Vector<double>) method."
00208 << std::endl
00209 << "Lower bound of variable "<< i
00210 << " is greater than upper bound of that variable."
00211 << std::endl << std::endl;
00212
00213 exit(1);
00214 }
00215 }
00216 }
00217
00218
00219
00220 lowerBound = newLowerBound;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 void ObjectiveFunction::setUpperBound(Vector<double> newUpperBound)
00234 {
00235 if(newUpperBound.getSize() != numberOfVariables)
00236 {
00237 std::cout << std::endl
00238 << "Error: ObjectiveFunction class. "
00239 << "void setUpperBound(Vector<double>) method."
00240 << std::endl
00241 << "Size must be equal to number of variables." << std::endl
00242 << std::endl;
00243
00244 exit(1);
00245 }
00246 else
00247 {
00248
00249
00250 for(int i = 0; i < numberOfVariables; i++)
00251 {
00252 if(newUpperBound[i] < lowerBound[i])
00253 {
00254 std::cout << std::endl
00255 << "Error: ObjectiveFunction class. "
00256 << "void setUpperBound(Vector<double>) method."
00257 << std::endl
00258 << "Upper bound of variable "<< i
00259 << " is less than lower bound of that variable."
00260 << std::endl << std::endl;
00261
00262 exit(1);
00263 }
00264 }
00265 }
00266
00267
00268
00269 upperBound = newUpperBound;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 void ObjectiveFunction::setDomain(Matrix<double> newDomain)
00284 {
00285 if(newDomain.getNumberOfRows() != 2)
00286 {
00287 std::cout << std::endl
00288 << "Error: ObjectiveFunction class. "
00289 << "void setDomain(Matrix<double>) method."
00290 << std::endl
00291 << "Number of rows must be 2."
00292 << std::endl << std::endl;
00293
00294 exit(1);
00295 }
00296 else if(newDomain.getNumberOfColumns() != numberOfVariables)
00297 {
00298 std::cout << std::endl
00299 << "Error: ObjectiveFunction class. "
00300 << "void setDomain(Matrix<double>) method."
00301 << std::endl
00302 << "Number of columns must be equal to number of variables."
00303 << std::endl
00304 << std::endl;
00305
00306 exit(1);
00307 }
00308 else
00309 {
00310
00311
00312 for(int i = 0; i < numberOfVariables; i++)
00313 {
00314 if(newDomain[0][i] > newDomain[1][i])
00315 {
00316 std::cout << std::endl
00317 << "Error: ObjectiveFunction class. "
00318 << "void setDomain(Matrix<double>) method."
00319 << std::endl
00320 << "Lower bound of input variable "<< i
00321 << " is greater than upper bound of that variable."
00322 << std::endl << std::endl;
00323
00324 exit(1);
00325 }
00326 }
00327 }
00328
00329
00330
00331 for(int i = 0; i < numberOfVariables; i++)
00332 {
00333 lowerBound[i] = newDomain[0][i];
00334 upperBound[i] = newDomain[1][i];
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 void ObjectiveFunction::setEpsilon(double newEpsilon)
00350 {
00351 if(newEpsilon <= 0.0)
00352 {
00353 std::stringstream buffer;
00354
00355 buffer << std::endl
00356 << "Error: ObjectiveFunction class. "
00357 << "void setEpsilon(double) method." << std::endl
00358 << "Epsilon must be greater than 0." << std::endl
00359 << std::endl;
00360
00361 throw std::invalid_argument(buffer.str());
00362
00363 }
00364 else
00365 {
00366 epsilon = newEpsilon;
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 void ObjectiveFunction::setNumberOfEvaluations(int newNumberOfEvaluations)
00382 {
00383 numberOfEvaluations = newNumberOfEvaluations;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 Vector<double> ObjectiveFunction::getGradient(Vector<double> argument)
00398 {
00399 Vector<double> gradient(numberOfVariables, 0.0);
00400
00401 double evaluation1 = 0.0, evaluation2 = 0.0;
00402
00403 for (int i = 0; i < numberOfVariables; i++)
00404 {
00405
00406
00407 argument[i] += epsilon;
00408
00409
00410
00411 evaluation2 = getEvaluation(argument);
00412
00413
00414
00415 argument[i] -= epsilon;
00416
00417
00418
00419 argument[i] -= epsilon;
00420
00421
00422
00423 evaluation1 = getEvaluation(argument);
00424
00425
00426
00427 argument[i] += epsilon;
00428
00429
00430
00431 gradient[i] = (evaluation2 - evaluation1)/(2.0*epsilon);
00432 }
00433
00434 return(gradient);
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 double ObjectiveFunction::getGradientNorm(Vector<double> gradient)
00447 {
00448 double gradientNorm = 0.0;
00449
00450 int numberOfDimensions = gradient.getSize();
00451
00452 double sum = 0.0;
00453
00454 for(int i = 0; i < numberOfDimensions; i++)
00455 {
00456 sum += pow(gradient[i], 2);
00457 }
00458
00459 gradientNorm = sqrt(sum);
00460
00461 return(gradientNorm);
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 Matrix<double> ObjectiveFunction::getHessian(Vector<double> argument)
00476 {
00477 Matrix<double> hessian(numberOfVariables, numberOfVariables, 0.0);
00478
00479 double evaluation11 = 0.0, evaluation12 = 0.0;
00480 double evaluation21 = 0.0, evaluation22 = 0.0;
00481
00482
00483
00484 for(int i = 0; i < numberOfVariables; i++)
00485 {
00486 for(int j = i; j < numberOfVariables; j++)
00487 {
00488
00489
00490 argument[i] += epsilon;
00491 argument[j] += epsilon;
00492
00493
00494
00495 evaluation22 = getEvaluation(argument);
00496
00497
00498
00499 argument[i] -= epsilon;
00500 argument[j] -= epsilon;
00501
00502
00503
00504
00505 argument[i] += epsilon;
00506 argument[j] -= epsilon;
00507
00508
00509
00510 evaluation21 = getEvaluation(argument);
00511
00512
00513
00514 argument[i] -= epsilon;
00515 argument[j] += epsilon;
00516
00517
00518
00519
00520 argument[i] -= epsilon;
00521 argument[j] += epsilon;
00522
00523
00524
00525 evaluation12 = getEvaluation(argument);
00526
00527
00528
00529 argument[i] += epsilon;
00530 argument[j] -= epsilon;
00531
00532
00533
00534
00535 argument[i] -= epsilon;
00536 argument[j] -= epsilon;
00537
00538
00539
00540 evaluation11 = getEvaluation(argument);
00541
00542
00543
00544 argument[i] += epsilon;
00545 argument[j] += epsilon;
00546
00547
00548
00549 hessian[i][j]
00550 = (evaluation22 - evaluation21 - evaluation12 + evaluation11)/(4.0*pow(epsilon,2));
00551 }
00552 }
00553
00554
00555
00556 for(int i = 0; i < numberOfVariables; i++)
00557 {
00558 for(int j = 0; j < i; j++)
00559 {
00560 hessian[i][j] = hessian[j][i];
00561 }
00562 }
00563
00564 return(hessian);
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 Matrix<double> ObjectiveFunction::getInverseHessian(Vector<double> argument)
00578 {
00579 Matrix<double> inverseHessian(numberOfVariables, numberOfVariables, 0.0);
00580
00581 Matrix<double> hessian = getHessian(argument);
00582
00583
00584 double hessianDeterminant = getDeterminant(hessian);
00585
00586 if(hessianDeterminant == 0.0)
00587 {
00588 std::cout << "Error: ObjectiveFunction class. "
00589 << "Matrix<double> getInverseHessian(Vector<double>) method."
00590 << std::endl
00591 << "Hessian matrix is singular." << std::endl
00592 << std::endl;
00593
00594 exit(1);
00595 }
00596
00597
00598
00599 Matrix<double> cofactor(numberOfVariables, numberOfVariables, 0.0);
00600
00601 Matrix<double> c(numberOfVariables-1, numberOfVariables-1, 0.0);
00602
00603 for(int j = 0; j < numberOfVariables; j++)
00604 {
00605 for (int i = 0; i < numberOfVariables; i++)
00606 {
00607
00608 int i1 = 0;
00609
00610 for(int ii = 0; ii < numberOfVariables; ii++)
00611 {
00612 if(ii == i)
00613 {
00614 continue;
00615 }
00616
00617 int j1 = 0;
00618
00619 for(int jj = 0; jj < numberOfVariables; jj++)
00620 {
00621 if (jj == j)
00622 {
00623 continue;
00624 }
00625
00626 c[i1][j1] = hessian[ii][jj];
00627 j1++;
00628 }
00629 i1++;
00630 }
00631
00632 double determinant = getDeterminant(c);
00633
00634 cofactor[i][j] = pow(-1.0, i+j+2.0)*determinant;
00635 }
00636 }
00637
00638
00639
00640 Matrix<double> adjoint(numberOfVariables, numberOfVariables, 0.0);
00641
00642 double temp = 0.0;
00643
00644 for(int i = 0; i < numberOfVariables; i++)
00645 {
00646 for (int j = 0; j < numberOfVariables; j++)
00647 {
00648 adjoint[i][j] = cofactor[j][i];
00649 }
00650 }
00651
00652
00653
00654 for(int i = 0; i < numberOfVariables; i++)
00655 {
00656 for(int j = 0; j < numberOfVariables; j++)
00657 {
00658 inverseHessian[i][j] = adjoint[i][j]/hessianDeterminant;
00659 }
00660 }
00661
00662
00663 return(inverseHessian);
00664 }
00665
00666
00667
00668
00669 void ObjectiveFunction::print(Vector<double> argument)
00670 {
00671
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681 double ObjectiveFunction::getDeterminant(Matrix<double> matrix)
00682 {
00683 double determinant = 0.0;
00684
00685 int numberOfRows = matrix.getNumberOfRows();
00686 int numberOfColumns = matrix.getNumberOfColumns();
00687
00688 if(numberOfRows != numberOfColumns)
00689 {
00690 std::cout << "Error: NewtonMethod class. "
00691 << "getDeterminant(Matrix<double>) method." << std::endl
00692 << "Matrix must be square" << std::endl
00693 << std::endl;
00694
00695 exit(1);
00696 }
00697
00698 if(numberOfRows == 0)
00699 {
00700 std::cout << "Error: NewtonMethod class. "
00701 << "getDeterminant(Matrix<double>) method." << std::endl
00702 << "Size of matrix is zero." << std::endl
00703 << std::endl;
00704
00705 exit(1);
00706 }
00707 else if(numberOfRows == 1)
00708 {
00709
00710
00711
00712
00713 determinant = matrix[0][0];
00714 }
00715 else if(numberOfRows == 2)
00716 {
00717 determinant = matrix[0][0]*matrix[1][1] - matrix[1][0]*matrix[0][1];
00718 }
00719 else
00720 {
00721 for(int j1 = 0; j1 < numberOfRows; j1++)
00722 {
00723 Matrix<double> subMatrix(numberOfRows-1, numberOfColumns-1, 0.0);
00724
00725 for(int i = 1; i < numberOfRows; i++)
00726 {
00727 int j2 = 0;
00728
00729 for (int j = 0; j < numberOfColumns; j++)
00730 {
00731 if (j == j1)
00732 {
00733 continue;
00734 }
00735
00736 subMatrix[i-1][j2] = matrix[i][j];
00737
00738 j2++;
00739 }
00740 }
00741
00742 determinant += pow(-1.0, j1+2.0)*matrix[0][j1]*getDeterminant(subMatrix);
00743 }
00744 }
00745
00746
00747 return(determinant);
00748 }
00749
00750 }
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768