mixed and homog. 2nd partial derivatives for multivar functions. hessian_f calculator.

This commit is contained in:
novak_99 2021-11-20 19:53:43 -08:00
parent 6e2d787fdf
commit 2b9155a624
5 changed files with 89 additions and 13 deletions

BIN
MLPP/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -14,6 +14,12 @@ namespace MLPP{
return (function(x + eps) - function(x)) / eps; // This is just the formal def. of the derivative.
}
double NumericalAnalysis::numDiff_2(double(*function)(double), double x){
double eps = 1e-5;
return (function(x + eps) - 2 * function(x) + function(x - eps)) / (eps * eps);
}
double NumericalAnalysis::numDiff(double(*function)(std::vector<double>), std::vector<double> x, int axis){
// For multivariable function analysis.
// This will be used for calculating Jacobian vectors.
@ -25,9 +31,26 @@ namespace MLPP{
return (function(x_eps) - function(x)) / eps;
}
double NumericalAnalysis::newtonRaphsonMethod(double(*function)(double), double x_0, double epoch){
double NumericalAnalysis::numDiff_2(double(*function)(std::vector<double>), std::vector<double> x, int axis1, int axis2){
//For Hessians.
double eps = 1e-5;
std::vector<double> x_pp = x;
x_pp[axis1] += eps;
x_pp[axis2] += eps;
std::vector<double> x_np = x;
x_np[axis2] += eps;
std::vector<double> x_pn = x;
x_pn[axis1] += eps;
return (function(x_pp) - function(x_np) - function(x_pn) + function(x))/(eps * eps);
}
double NumericalAnalysis::newtonRaphsonMethod(double(*function)(double), double x_0, double epoch_num){
double x = x_0;
for(int i = 0; i < epoch; i++){
for(int i = 0; i < epoch_num; i++){
x = x - function(x)/numDiff(function, x);
}
return x;
@ -41,4 +64,17 @@ namespace MLPP{
}
return jacobian;
}
std::vector<std::vector<double>> NumericalAnalysis::hessian(double(*function)(std::vector<double>), std::vector<double> x){
std::vector<std::vector<double>> hessian;
hessian.resize(x.size());
for(int i = 0; i < hessian.size(); i++){
hessian[i].resize(x.size());
}
for(int i = 0; i < hessian.size(); i++){
for(int j = 0; j < hessian[i].size(); j++){
hessian[i][j] = numDiff_2(function, x, i, j);
}
}
return hessian;
}
}

View File

@ -16,10 +16,15 @@ namespace MLPP{
the future.
*/
double numDiff(double(*function)(double), double x);
double numDiff(double(*function)(std::vector<double>), std::vector<double> x, int axis);
double newtonRaphsonMethod(double(*function)(double), double x_0, double epoch);
double numDiff_2(double(*function)(double), double x);
std::vector<double> jacobian(double(*function)(std::vector<double>), std::vector<double>);
double numDiff(double(*function)(std::vector<double>), std::vector<double> x, int axis);
double numDiff_2(double(*function)(std::vector<double>), std::vector<double> x, int axis1, int axis2);
double newtonRaphsonMethod(double(*function)(double), double x_0, double epoch_num);
std::vector<double> jacobian(double(*function)(std::vector<double>), std::vector<double> x); // Indeed, for functions with scalar outputs the Jacobians will be vectors.
std::vector<std::vector<double>> hessian(double(*function)(std::vector<double>), std::vector<double> x);
};
}

BIN
a.out Executable file

Binary file not shown.

View File

@ -52,12 +52,41 @@ using namespace MLPP;
double f(double x){
return x*x*x + 2*x - 2;
}
/*
y = x^3 + 2x - 2
y' = 3x^2 + 2
y'' = 6x
y''(2) = 12
*/
// double f_mv(std::vector<double> x){
// return x[0] * x[0] + x[0] * x[1] * x[1] + x[1] + 5;
// }
/*
Where x, y = x[0], x[1], this function is defined as:
f(x, y) = x^2 + xy^2 + y + 5
f/x = 2x + 2y
^2f/xy = 2
*/
double f_mv(std::vector<double> x){
return x[0] * x[0] + x[1] * x[1] + x[1] + 5;
// Where x,y=x[0],x[1], this function is defined as:
// f(x,y) = x^2 + y^2 + y + 5
return x[0] * x[0] * x[0] + x[0] + x[1] * x[1] * x[1] * x[0] + x[2] * x[2] * x[1];
}
/*
Where x, y = x[0], x[1], this function is defined as:
f(x, y) = x^4 + xy^3 + yz^2
f/x = 3x^2 + 3y^2
^2f/x^2 = 6x
f/z = 2zy
^2f/z^2 = 2z
f/y = 3xy^2
^2f/yx = 3y^2
*/
int main() {
@ -475,12 +504,18 @@ int main() {
// Checks for numerical analysis class.
NumericalAnalysis numAn;
std::cout << numAn.numDiff(&f, 1) << std::endl;
std::cout << numAn.newtonRaphsonMethod(&f, 1, 1000) << std::endl;
// std::cout << numAn.numDiff(&f, 1) << std::endl;
// std::cout << numAn.newtonRaphsonMethod(&f, 1, 1000) << std::endl;
std::cout << numAn.numDiff(&f_mv, {1, 1}, 1) << std::endl; // Derivative w.r.t. x.
// std::cout << numAn.numDiff(&f_mv, {1, 1}, 1) << std::endl; // Derivative w.r.t. x.
alg.printVector(numAn.jacobian(&f_mv, {1, 1}));
// alg.printVector(numAn.jacobian(&f_mv, {1, 1}));
//std::cout << numAn.numDiff_2(&f, 2) << std::endl;
std::cout << numAn.numDiff_2(&f_mv, {2, 2, 500}, 2, 2) << std::endl;
std::cout << "Our Hessian." << std::endl;
alg.printMatrix(numAn.hessian(&f_mv, {2, 2, 500}));
return 0;
}