mirror of
https://github.com/Relintai/MLPP.git
synced 2025-02-04 15:55:53 +01:00
Added 2nd partial derivative test. Detects saddles, mins and maxes.
This commit is contained in:
parent
5764f20ed2
commit
66883a3f5d
@ -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++){
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user