78 #include <cppad/cppad.hpp>
82 #include "CoinHelperFunctions.hpp"
83 #include "OSInstance.h"
85 #include "OSParameters.h"
90 #include "OSInstance.h"
103 WindowsErrorPopupBlocker();
109 std::cout.precision(12);
112 double x0,
double x1,
double x2,
double x3,
double y0,
double y1,
double z );
114 double x0,
double x1,
double x2,
double x3,
double y0,
double y1,
double z );
116 double x0,
double x1,
double x2,
double x3,
double y0,
double y1,
double z );
123 std::string osilFileName;
126 const char dirsep = CoinFindDirSeparator();
129 dataDir = dirsep ==
'/' ?
"../data/" :
"..\\data\\";
131 osilFileName = dataDir +
"osilFiles" + dirsep +
"CppADTestLag.osil";
132 std::cout <<
"osilFileName = " << osilFileName << std::endl;
144 osinstance = osilreader->
readOSiL( osil);
145 std::vector<double> funVals(3);
146 std::vector<double> dfunVals(6);
147 double *conVals = NULL;
149 double *objVals = NULL;
167 std::cout <<
"Initialize Nonlinear Structures" << std::endl;
178 std::map<int, int> varIndexMap;
179 std::map<int, int>::iterator posVarIndexMap;
185 for(posVarIndexMap = varIndexMap.begin(); posVarIndexMap != varIndexMap.end(); ++posVarIndexMap){
186 std::cout <<
"Variable Index = " << posVarIndexMap->first << std::endl ;
188 std::cout <<
"Number of nonlinear variables = " << varIndexMap.size() << std::endl;
198 for(jj = 0; jj < mm; jj++){
202 std::cout <<
"Number of unique nonlinear terms = " << mm << std::endl;
208 size_t n = varIndexMap.size();
212 std::vector<double>
x0( n);
220 std::cout <<
"CALL forward" << std::endl;
222 for( kjl = 0; kjl < 3; kjl++){
223 std::cout <<
"forward 0 " << funVals[ kjl] << std::endl;
226 std::vector<double>
x1( n);
230 std::cout <<
"Now get the third column of the Jacobian forwardAD(1, x1)" << std::endl;
232 for( kjl = 0; kjl < 3; kjl++){
233 std::cout <<
"forward 1 " << funVals[ kjl] << std::endl;
249 std::vector<double>
x2( n);
253 std::cout <<
"Now calcuate forwardAD(2, x2)" << std::endl;
255 for( kjl = 0; kjl < 3; kjl++){
256 std::cout <<
"forward 2 " << funVals[ kjl] << std::endl;
266 std::vector<double> vlambda(3);
271 std::cout <<
"Now get the third row of the Jacobian reverseAD(1, vlambda)" << std::endl;
273 funVals = osinstance->
reverseAD(1, vlambda);
274 for( kjl = 0; kjl < 3; kjl++){
275 std::cout <<
"reverse 1 " << funVals[ kjl] << std::endl;
302 dfunVals = osinstance->
reverseAD(2, vlambda);
304 std::cout <<
"Here are the first partials of the Lagrangain" << std::endl;
305 for(
int kjl = 0; kjl <= 4; kjl+=2){
306 std::cout << dfunVals[ kjl] << std::endl;
313 std::cout <<
"Here is the third row (column) of Hessian of Lagrangian" << std::endl;
314 for(
int kjl = 1; kjl <= 5; kjl+=2){
315 std::cout << dfunVals[ kjl] << std::endl;
322 double*
x =
new double[4];
323 double* z =
new double[2];
324 double*
w =
new double[1];
363 std::cout <<
"Calculate objective, idx = -1" << std::endl;
366 std::cout <<
"Calculate first constraint, idx = 0" << std::endl;
367 std::cout <<
"constraint index 0 value = " << osinstance->
calculateFunctionValue(0, x,
true) << std::endl;
369 std::cout <<
"Now use calculateAllConstraintFunctionValues" << std::endl;
372 std::cout <<
"CONSTRAINT FUNCTION INDEX = " << idx <<
" CONSTRAINT FUNCTION VALUE = " << *(conVals + idx) << std::endl;
375 std::cout <<
"Now use calculateAllObjectiveFunctionValues" << std::endl;
378 std::cout <<
"OBJECTIVE FUNCTION INDEX = " << idx <<
" OBJECTIVE FUNCTION VALUE = " << *(objVals + idx) << std::endl;
382 std::cout <<
"FAILED CHECKING FUNCTION VALUES TEST" << std::endl;
386 std::cout <<
"PASSED CHECKING FUNCTION VALUES TEST" << std::endl;
395 std::cout <<
"PLACE CALL TO JACOBIAN SPARSITY PATTERN" << std::endl;
399 std::cout <<
"JACOBIAN SPARSITY PATTERN" << std::endl;
400 std::cout <<
"JACOBIAN START SIZE " << sparseJac->
startSize << std::endl;
405 std::cout <<
"number constant terms in constraint " << idx <<
" is "
406 << *(sparseJac->
conVals + idx) << std::endl;
407 for(k = *(sparseJac->
starts + idx); k < *(sparseJac->
starts + idx + 1); k++){
408 std::cout <<
"row idx = " << idx <<
" col idx = "<< *(sparseJac->
indexes +
k) << std::endl;
415 std::cout <<
"GET LAGRANGIAN HESSIAN SPARSITY PATTERN" << std::endl;
418 std::cout <<
"Row Index = " << *(sparseHessian->
hessRowIdx + idx) ;
419 std::cout <<
" Column Index = " << *(sparseHessian->
hessColIdx + idx) << std::endl;
438 std::cout <<
"OBJECTIVE FUNCTION GRADIENT" << std::endl;
442 std::cout <<
"col idxx = " << idx <<
" value = " << *(objGrad + idx) << std::endl;
444 std::cout <<
"CONSTRAINT JACOBIAN MATRIX" << std::endl;
448 for(k = *(sparseJac->
starts + idx); k < *(sparseJac->
starts + idx + 1); k++){
449 std::cout <<
"row idx = " << idx <<
" col idx = "<< *(sparseJac->
indexes +
k)
450 <<
" value = " << *(sparseJac->
values + k) << std::endl;
455 std::cout <<
"FAILED THE GRADIENT TEST" << std::endl;
459 std::cout <<
"PASSED THE GRADIENT TEST" << std::endl;
471 std::cout <<
"GET LAGRANGIAN HESSIAN FIRST TIME" << std::endl;
474 std::cout <<
"row idx = " << *(sparseHessian->
hessRowIdx + idx) <<
475 " col idx = "<< *(sparseHessian->
hessColIdx + idx)
476 <<
" value = " << *(sparseHessian->
hessValues + idx) << std::endl;
478 ok =
CheckHessianUpper( sparseHessian, x[0], x[1], x[2], x[3], z[0], z[1], w[0]);
480 std::cout <<
"FAILED THE FIRST HESSIAN TEST" << std::endl;
484 std::cout <<
"PASSED THE FIRST HESSIAN TEST" << std::endl;
492 std::cout <<
"NOW GET LAGRANGIAN HESSIAN SECOND TIME FOR x[0] = 5" << std::endl;
516 std::cout <<
"row idx = " << *(sparseHessian->
hessRowIdx + idx) <<
517 " col idx = "<< *(sparseHessian->
hessColIdx + idx)
518 <<
" value = " << *(sparseHessian->
hessValues + idx) << std::endl;
520 ok =
CheckHessianUpper( sparseHessian , x[0], x[1], x[2], x[3], z[0], z[1], w[0] );
522 std::cout <<
"FAILED THE SECOND HESSIAN TEST" << std::endl;
526 std::cout <<
"PASSED THE SECOND HESSIAN TEST" << std::endl << std::endl ;
531 std::cout <<
"HERE IS ROW 1 OF JACOBIAN MATRIX" << std::endl;
533 for(k = *(sparseJac->
starts + idx); k < *(sparseJac->
starts + idx + 1); k++){
534 std::cout <<
"row idx = " << idx <<
" col idx = "<< *(sparseJac->
indexes +
k)
535 <<
" value = " << *(sparseJac->
values + k) << std::endl;
537 std::cout << std::endl;
545 std::cout <<
"HERE IS ROW 1 HESSIAN MATRIX" << std::endl;
547 std::cout <<
"row idx = " << *(sparseHessian->
hessRowIdx + idx) <<
548 " col idx = "<< *(sparseHessian->
hessColIdx + idx)
549 <<
" value = " << *(sparseHessian->
hessValues + idx) << std::endl;
556 ok =
CheckHessianUpper( sparseHessian , x[0], x[1], x[2], x[3], z[0], z[1], w[0] );
558 std::cout <<
"FAILED THE THIRD HESSIAN TEST" << std::endl;
562 std::cout <<
"PASSED THE THIRD HESSIAN TEST" << std::endl << std::endl ;
573 CppADvector< AD<double> > X(n);
574 CppADvector< AD<double> > Y(m);
580 std::cout <<
"Start Taping" << std::endl;
581 CppAD::Independent( X);
584 Y[ 0] = CppAD::pow(X[0], 2) + 9*X[1];
585 Y[ 1] = 33 - 105 + 1.37*X[1] + 2*X[3] + 5*X[1] ;
586 Y[ 2] =
log(X[0]*X[3]) + 7*X[2] ;
588 CppAD::ADFun<double>
f(X, Y);
589 std::cout <<
"Stop Taping" << std::endl;
591 std::vector<double> x_vec( n);
596 funVals = f.Forward(0, x_vec);
597 conVals[ 0] = funVals[ 1];
598 std::cout <<
"conVals[ 0] = " << conVals[ 0] << std::endl;
599 conVals[ 1] = funVals[ 2];
600 std::cout <<
"conVals[ 1] = " << conVals[ 1] << std::endl;
601 objVals[ 0] = funVals[ 0];
602 std::cout <<
"objVals[ 0] = " << objVals[ 0] << std::endl;
603 ok =
CheckFunctionValues( conVals, funVals[ 0], x[ 0], x[1], x[2], x[3], z[0], z[1], w[0] );
605 std::cout <<
"FAILED CHECKING FUNCTION VALUES TEST" << std::endl;
609 std::cout <<
"PASSED CHECKING FUNCTION VALUES TEST" << std::endl;
614 std::vector<double> unit_col_vec( n);
615 std::vector<double> lagMultipliers( m);
616 std::vector<double> gradVals( m);
617 lagMultipliers[ 0] = w[ 0];
618 lagMultipliers[ 1] = z[ 0];
619 lagMultipliers[ 2] = z[ 1];
620 unsigned int index, kj;
622 for(index = 0; index <
n; index++){
623 unit_col_vec[ index] = 0;
625 for(index = 0; index <
n; index++){
626 unit_col_vec[ index] = 1;
628 gradVals = f.Forward(1, unit_col_vec);
629 unit_col_vec[ index] = 0;
631 for(kj = 0; kj <
m; kj++){
632 std::cout <<
"variable " << index <<
" row " << kj <<
" gradient value" << std::endl;
633 std::cout <<
"gradient value = " << gradVals[ kj] << std::endl;
636 std::cout <<
"CALL f.Reverse -------" << std::endl;
637 f.Reverse(2, lagMultipliers);
638 std::cout <<
"FINISH CALL f.Reverse -------" << std::endl;
644 std::cout <<
"OSILREADER DELETED" << std::endl;
652 std::cout << eclass.
errormsg << std::endl;
661 CppADvector< AD<double> >
x(n);
665 CppAD::Independent(x);
668 CppADvector< AD<double> > y(m);
669 y[0] = std::pow(x0, x1);
671 CppAD::ADFun<double>
f(x, y);
673 double check = std::pow(x0, x1);
675 std::vector<double> dx(n);
676 std::vector<double> dy(m);
679 dy = f.Forward(1, dx);
680 std::cout <<
"dy = " << dy[ 0] << std::endl;
681 check = x1 * std::pow(x0, x1-1.);
691 CPPAD_TEST_VECTOR< AD<double> > X(n);
696 CppAD::Independent(X);
699 CPPAD_TEST_VECTOR< AD<double> > Y(m);
700 Y[0] = CppAD::pow(X[0], 2) + CppAD::pow(X[2], 2);
701 Y[1] = -CppAD::pow(X[0], 2) + CppAD::pow(X[1], 2);
703 CppAD::ADFun<double>
f(X, Y);
706 std::vector<bool>
r(n * n);
708 for(i = 0; i <
n; i++) {
709 for(j = 0; j <
n; j++)
710 r[ i * n + j ] =
false;
711 r[ i * n + i ] =
true;
714 f.ForSparseJac(n, r);
730 std::vector<bool>
e( m);
732 for(i = 0; i <
m; i++)
736 std::vector<bool> h( n*n);
738 std::cout <<
"Computing Sparse Hessian" << std::endl;
739 h = f.RevSparseHes(n, e);
740 for(i = 0; i <
n; i++){
741 std::cout <<
"Row " << i <<
" of Hessian " << std::endl;
742 for(j = 0; j <
n; j++){
743 std::cout << h[ i*n +
j] <<
" ";
745 std::cout << std::endl;
749 std::cout <<
"\nTEST OF ALGORITHMIC DIFFERENTIATION CONCLUDED SUCCESSFULLY\n";
754 double x0,
double x1,
double x2,
double x3,
double z0,
double z1,
double w ){
755 using CppAD::NearEqual;
757 double checkObj = x0*x0 + 9*
x1;
758 std::cout <<
"checkObj = " << checkObj << std::endl;
759 std::cout <<
"objValue = " << objValue << std::endl;
762 double checkCon0 = 33. - 105. + 1.37*x1 + 2*x3 + 5*
x1;
763 std::cout <<
"checkCon0 = " << checkCon0 << std::endl;
764 std::cout <<
"conVals = " << *(conVals + 0) << std::endl;
767 double checkCon1 =
log(x0*x3) + 7*
x2;
768 std::cout <<
"checkCon1 = " << checkCon1 << std::endl;
769 std::cout <<
"conVals = " << *(conVals + 1) << std::endl;
777 double x0,
double x1,
double x2,
double x3,
double y0,
double y1,
double w ){
778 using CppAD::NearEqual;
781 double checkObjPartial0 = 2*
x0;
784 double checkObjPartial1 = 9;
787 double checkObjPartial2 = 0;
792 double checkCon0Partial1 = 1.37 + 5.0;
795 double checkCon0Partial3 = 2.;
799 double checkCon1Partial2 = 7;
802 double checkCon1Partial0 = 1./
x0;
805 double checkCon1Partial3 = 1./x3;
812 double x0,
double x1,
double x2,
double x3,
double z0,
double z1,
double w ){
813 using CppAD::NearEqual;
815 int hessValuesIdx = 0;
818 double check = 2. * w - z1 / (x0 *
x0);
819 ok &= NearEqual(*(sparseHessian->
hessValues + hessValuesIdx++), check, 1
e-10, 1
e-10);
820 if(ok ==
false) std::cout <<
"FAILED ONE" << std::endl;
821 ok &= NearEqual(*(sparseHessian->
hessValues + hessValuesIdx++), 0., 1
e-10, 1
e-10);
822 if(ok ==
false) std::cout <<
"FAILED TWO" << std::endl;
824 check = - z1 / (x3 * x3);
825 ok &= NearEqual(*(sparseHessian->
hessValues + hessValuesIdx++), check, 1
e-10, 1
e-1);
826 if(ok ==
false) std::cout <<
"FAILED THREE" << std::endl;
bool CheckFunctionValues(double *conVals, double objValue, double x0, double x1, double x2, double x3, double z0, double z1, double w)
This file defines the OSnLNode class along with its derived classes.
SparseHessianMatrix * calculateLagrangianHessian(double *x, double *objLambda, double *conLambda, bool new_x, int highestOrder)
Calculate the Hessian of the Lagrangian Expression Tree This method will build the CppAD expression t...
double * values
values holds a double array of nonzero partial derivatives
double calculateFunctionValue(int idx, double *x, bool new_x)
Calculate the function value for function (constraint or objective) indexed by idx.
bool bUseExpTreeForFunEval
bUseExpTreeForFunEval is set to true if you wish to use the OS Expression Tree for function evaluatio...
int getVariableNumber()
Get number of variables.
SparseHessianMatrix * calculateHessian(double *x, int idx, bool new_x)
Calculate the Hessian of a constraint or objective function.
std::string errormsg
errormsg is the error that is causing the exception to be thrown
int main(int argc, char *argv[])
int * getNonlinearExpressionTreeModIndexes()
Get all the nonlinear expression tree indexes, i.e., indexes of rows (objectives or constraints) that...
int startSize
startSize is the dimension of the starts array – should equal number of rows + 1
SparseJacobianMatrix * calculateAllConstraintFunctionGradients(double *x, double *objLambda, double *conLambda, bool new_x, int highestOrder)
Calculate the gradient of all constraint functions.
int getNumberOfNonlinearExpressionTreeModIndexes()
Get the number of unique nonlinear expression tree indexes after modifying the expression tree to con...
int * hessColIdx
hessColIdx is an integer array of column indices in the range 0, ..., n - 1.
int getObjectiveNumber()
Get number of objectives.
bool CheckHessianUpper(SparseHessianMatrix *sparseHessian, double x0, double x1, double x2, double x3, double z0, double z1, double w)
OSInstance * readOSiL(const std::string &osil)
parse the OSiL model instance.
std::map< int, int > getAllNonlinearVariablesIndexMap()
int * hessRowIdx
hessRowIdx is an integer array of row indices in the range 0, ..., n - 1.
void fint fint fint real fint real real real real * f
SparseJacobianMatrix * getJacobianSparsityPattern()
void fint fint fint real fint real real real real real real real real real * e
Used to read an OSiL string.
int * indexes
indexes holds an integer array of variable indices.
double * calculateAllConstraintFunctionValues(double *x, double *objLambda, double *conLambda, bool new_x, int highestOrder)
Calculate all of the constraint function values.
int hessDimension
hessDimension is the number of nonzeros in each array.
SparseHessianMatrix * getLagrangianHessianSparsityPattern()
double * hessValues
hessValues is a double array of the Hessian values.
void fint fint fint real fint real real real real real real real * r
a sparse Jacobian matrix data structure
#define OS_NEAR_EQUAL
we use OS_NEAR_EQUAL in unitTest to see if we are close to the optimal obj value
int * starts
starts holds an integer array of start elements, each start element points to the start of partials f...
int getConstraintNumber()
Get number of constraints.
std::string getFileAsString(const char *fname)
read a file and return contents as a string.
bool initForAlgDiff()
This should be called by nonlinear solvers using callback functions.
double * calculateAllObjectiveFunctionValues(double *x, double *objLambda, double *conLambda, bool new_x, int highestOrder)
Calculate all of the objective function values.
std::vector< double > reverseAD(int p, std::vector< double > vdlambda)
Perform an AD reverse sweep.
The in-memory representation of an OSiL instance..
int * conVals
conVals holds an integer array of integers, conVals[i] is the number of constant terms in the gradien...
class used to make it easy to read and write files.
void fint fint fint real fint real real real real real real real real * w
The in-memory representation of a SparseHessianMatrix..
bool CheckGradientValues(SparseJacobianMatrix *sparseJac, double *objGrad, double x0, double x1, double x2, double x3, double y0, double y1, double w)
used for throwing exceptions.
std::vector< double > forwardAD(int p, std::vector< double > vdX)
Perform an AD forward sweep.
double * calculateObjectiveFunctionGradient(double *x, double *objLambda, double *conLambda, int objIdx, bool new_x, int highestOrder)
Calculate the gradient of the objective function indexed by objIdx.
void fint fint fint real fint real * x
CouExpr & log(CouExpr &e)