Added 2nd partial derivative test. Detects saddles, mins and maxes.

This commit is contained in:
novak_99 2021-11-29 15:08:41 -08:00
parent 5764f20ed2
commit 66883a3f5d
4 changed files with 73 additions and 0 deletions

View File

@ -704,6 +704,34 @@ namespace MLPP{
return true;
}
bool LinAlg::negativeDefiniteChecker(std::vector<std::vector<double>> A){
auto [eigenvectors, eigenvals] = eig(A);
std::vector<double> eigenvals_vec;
for(int i = 0; i < eigenvals.size(); i++){
eigenvals_vec.push_back(eigenvals[i][i]);
}
for(int i = 0; i < eigenvals_vec.size(); i++){
if(eigenvals_vec[i] >= 0){ // Simply check to ensure all eigenvalues are negative.
return false;
}
}
return true;
}
bool LinAlg::zeroEigenvalue(std::vector<std::vector<double>> A){
auto [eigenvectors, eigenvals] = eig(A);
std::vector<double> eigenvals_vec;
for(int i = 0; i < eigenvals.size(); i++){
eigenvals_vec.push_back(eigenvals[i][i]);
}
for(int i = 0; i < eigenvals_vec.size(); i++){
if(eigenvals_vec[i] == 0){
return true;
}
}
return false;
}
void LinAlg::printMatrix(std::vector<std::vector<double>> A){
for(int i = 0; i < A.size(); i++){
for(int j = 0; j < A[i].size(); j++){

View File

@ -105,6 +105,10 @@ namespace MLPP{
std::vector<double> solve(std::vector<std::vector<double>> A, std::vector<double> b);
bool positiveDefiniteChecker(std::vector<std::vector<double>> A);
bool negativeDefiniteChecker(std::vector<std::vector<double>> A);
bool zeroEigenvalue(std::vector<std::vector<double>> A);
void printMatrix(std::vector<std::vector<double>> A);

View File

@ -260,4 +260,43 @@ namespace MLPP{
}
return laplacian;
}
std::string NumericalAnalysis::secondPartialDerivativeTest(double(*function)(std::vector<double>), std::vector<double> x){
LinAlg alg;
std::vector<std::vector<double>> hessianMatrix = hessian(function, x);
/*
The reason we do this is because the 2nd partial derivative test is less conclusive for functions of variables greater than
2, and the calculations specific to the bivariate case are less computationally intensive.
*/
if(x.size() == 2){
double det = alg.det(hessianMatrix, hessianMatrix.size());
double secondDerivative = numDiff_2(function, x, 0, 0);
if(secondDerivative > 0 && det > 0){
return "min";
}
else if(secondDerivative < 0 && det > 0){
return "max";
}
else if(det < 0){
return "saddle";
}
else{
return "test was inconclusive";
}
}
else {
if(alg.positiveDefiniteChecker(hessianMatrix)){
return "min";
}
else if(alg.negativeDefiniteChecker(hessianMatrix)){
return "max";
}
else if(!alg.zeroEigenvalue(hessianMatrix)){
return "saddle";
}
else{
return "test was inconclusive";
}
}
}
}

View File

@ -48,6 +48,8 @@ namespace MLPP{
double laplacian(double(*function)(std::vector<double>), std::vector<double> x); // laplacian
std::string secondPartialDerivativeTest(double(*function)(std::vector<double>), std::vector<double> x);
};
}