summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/yap/example/autodiff_library
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/yap/example/autodiff_library
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/yap/example/autodiff_library')
-rw-r--r--src/boost/libs/yap/example/autodiff_library/ActNode.cpp34
-rw-r--r--src/boost/libs/yap/example/autodiff_library/ActNode.h29
-rw-r--r--src/boost/libs/yap/example/autodiff_library/BinaryOPNode.cpp651
-rw-r--r--src/boost/libs/yap/example/autodiff_library/BinaryOPNode.h57
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Edge.cpp54
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Edge.h33
-rw-r--r--src/boost/libs/yap/example/autodiff_library/EdgeSet.cpp76
-rw-r--r--src/boost/libs/yap/example/autodiff_library/EdgeSet.h33
-rw-r--r--src/boost/libs/yap/example/autodiff_library/LICENSE22
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Node.cpp32
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Node.h65
-rw-r--r--src/boost/libs/yap/example/autodiff_library/OPNode.cpp37
-rw-r--r--src/boost/libs/yap/example/autodiff_library/OPNode.h37
-rw-r--r--src/boost/libs/yap/example/autodiff_library/PNode.cpp147
-rw-r--r--src/boost/libs/yap/example/autodiff_library/PNode.h47
-rw-r--r--src/boost/libs/yap/example/autodiff_library/README.md10
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Stack.cpp58
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Stack.h38
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Tape.cpp16
-rw-r--r--src/boost/libs/yap/example/autodiff_library/Tape.h97
-rw-r--r--src/boost/libs/yap/example/autodiff_library/UaryOPNode.cpp375
-rw-r--r--src/boost/libs/yap/example/autodiff_library/UaryOPNode.h52
-rw-r--r--src/boost/libs/yap/example/autodiff_library/VNode.cpp149
-rw-r--r--src/boost/libs/yap/example/autodiff_library/VNode.h52
-rw-r--r--src/boost/libs/yap/example/autodiff_library/auto_diff_types.h26
-rw-r--r--src/boost/libs/yap/example/autodiff_library/autodiff.cpp335
-rw-r--r--src/boost/libs/yap/example/autodiff_library/autodiff.h114
27 files changed, 2676 insertions, 0 deletions
diff --git a/src/boost/libs/yap/example/autodiff_library/ActNode.cpp b/src/boost/libs/yap/example/autodiff_library/ActNode.cpp
new file mode 100644
index 00000000..c21594f8
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/ActNode.cpp
@@ -0,0 +1,34 @@
+/*
+ * ActNode.cpp
+ *
+ * Created on: 13 Apr 2013
+ * Author: s0965328
+ */
+
+#include "ActNode.h"
+
+namespace AutoDiff {
+
+ActNode::ActNode() : AutoDiff::Node(),adj(NaN_Double){
+
+}
+
+ActNode::~ActNode() {
+}
+
+
+void ActNode::update_adj(double& v)
+{
+ assert(!isnan(adj));
+ assert(!isnan(v));
+ adj+=v;
+}
+
+void ActNode::grad_reverse_1_init_adj()
+{
+ adj = 1;
+}
+
+}
+
+
diff --git a/src/boost/libs/yap/example/autodiff_library/ActNode.h b/src/boost/libs/yap/example/autodiff_library/ActNode.h
new file mode 100644
index 00000000..58e77cc3
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/ActNode.h
@@ -0,0 +1,29 @@
+/*
+ * ActNode.h
+ *
+ * Created on: 13 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef ACTNODE_H_
+#define ACTNODE_H_
+
+#include "Node.h"
+
+
+namespace AutoDiff {
+
+class ActNode : public Node{
+public:
+ ActNode();
+ virtual ~ActNode();
+
+ void update_adj(double& v);
+ void grad_reverse_1_init_adj();
+
+ double adj;
+};
+
+} // end namespace foo
+
+#endif /* ACTNODE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/BinaryOPNode.cpp b/src/boost/libs/yap/example/autodiff_library/BinaryOPNode.cpp
new file mode 100644
index 00000000..992d692d
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/BinaryOPNode.cpp
@@ -0,0 +1,651 @@
+/*
+ * BinaryOPNode.cpp
+ *
+ * Created on: 6 Nov 2013
+ * Author: s0965328
+ */
+
+#include "auto_diff_types.h"
+#include "BinaryOPNode.h"
+#include "PNode.h"
+#include "Stack.h"
+#include "Tape.h"
+#include "EdgeSet.h"
+#include "Node.h"
+#include "VNode.h"
+#include "OPNode.h"
+#include "ActNode.h"
+#include "EdgeSet.h"
+
+namespace AutoDiff {
+
+BinaryOPNode::BinaryOPNode(OPCODE op_, Node* left_, Node* right_):OPNode(op_,left_),right(right_)
+{
+}
+
+OPNode* BinaryOPNode::createBinaryOpNode(OPCODE op, Node* left, Node* right)
+{
+ assert(left!=NULL && right!=NULL);
+ OPNode* node = NULL;
+ node = new BinaryOPNode(op,left,right);
+ return node;
+}
+
+BinaryOPNode::~BinaryOPNode() {
+ if(right->getType()!=VNode_Type)
+ {
+ delete right;
+ right = NULL;
+ }
+}
+
+void BinaryOPNode::inorder_visit(int level,ostream& oss){
+ if(left!=NULL){
+ left->inorder_visit(level+1,oss);
+ }
+ oss<<this->toString(level)<<endl;
+ if(right!=NULL){
+ right->inorder_visit(level+1,oss);
+ }
+}
+
+void BinaryOPNode::collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total){
+ total++;
+ if (left != NULL) {
+ left->collect_vnodes(nodes,total);
+ }
+ if (right != NULL) {
+ right->collect_vnodes(nodes,total);
+ }
+
+}
+
+void BinaryOPNode::eval_function()
+{
+ assert(left!=NULL && right!=NULL);
+ left->eval_function();
+ right->eval_function();
+ this->calc_eval_function();
+}
+
+void BinaryOPNode::calc_eval_function()
+{
+ double x = NaN_Double;
+ double rx = SV->pop_back();
+ double lx = SV->pop_back();
+ switch (op)
+ {
+ case OP_PLUS:
+ x = lx + rx;
+ break;
+ case OP_MINUS:
+ x = lx - rx;
+ break;
+ case OP_TIMES:
+ x = lx * rx;
+ break;
+ case OP_DIVID:
+ x = lx / rx;
+ break;
+ case OP_POW:
+ x = pow(lx,rx);
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented!!"<<endl;
+ assert(false);
+ break;
+ }
+ SV->push_back(x);
+}
+
+
+//1. visiting left if not NULL
+//2. then, visiting right if not NULL
+//3. calculating the immediate derivative hu and hv
+void BinaryOPNode::grad_reverse_0()
+{
+ assert(left!=NULL && right != NULL);
+ this->adj = 0;
+ left->grad_reverse_0();
+ right->grad_reverse_0();
+ this->calc_grad_reverse_0();
+}
+
+//right left - right most traversal
+void BinaryOPNode::grad_reverse_1()
+{
+ assert(right!=NULL && left!=NULL);
+ double r_adj = SD->pop_back()*this->adj;
+ right->update_adj(r_adj);
+ double l_adj = SD->pop_back()*this->adj;
+ left->update_adj(l_adj);
+
+ right->grad_reverse_1();
+ left->grad_reverse_1();
+}
+
+void BinaryOPNode::calc_grad_reverse_0()
+{
+ assert(left!=NULL && right != NULL);
+ double l_dh = NaN_Double;
+ double r_dh = NaN_Double;
+ double rx = SV->pop_back();
+ double lx = SV->pop_back();
+ double x = NaN_Double;
+ switch (op)
+ {
+ case OP_PLUS:
+ x = lx + rx;
+ l_dh = 1;
+ r_dh = 1;
+ break;
+ case OP_MINUS:
+ x = lx - rx;
+ l_dh = 1;
+ r_dh = -1;
+ break;
+ case OP_TIMES:
+ x = lx * rx;
+ l_dh = rx;
+ r_dh = lx;
+ break;
+ case OP_DIVID:
+ x = lx / rx;
+ l_dh = 1 / rx;
+ r_dh = -(lx) / pow(rx, 2);
+ break;
+ case OP_POW:
+ if(right->getType()==PNode_Type){
+ x = pow(lx,rx);
+ l_dh = rx*pow(lx,(rx-1));
+ r_dh = 0;
+ }
+ else{
+ assert(lx>0.0); //otherwise log(lx) is not defined in read number
+ x = pow(lx,rx);
+ l_dh = rx*pow(lx,(rx-1));
+ r_dh = pow(lx,rx)*log(lx); //this is for x1^x2 when x1=0 cause r_dh become +inf, however d(0^x2)/d(x2) = 0
+ }
+ break;
+ default:
+ cerr<<"error op not impl"<<endl;
+ break;
+ }
+ SV->push_back(x);
+ SD->push_back(l_dh);
+ SD->push_back(r_dh);
+}
+
+void BinaryOPNode::hess_reverse_0_init_n_in_arcs()
+{
+ this->left->hess_reverse_0_init_n_in_arcs();
+ this->right->hess_reverse_0_init_n_in_arcs();
+ this->Node::hess_reverse_0_init_n_in_arcs();
+}
+
+void BinaryOPNode::hess_reverse_1_clear_index()
+{
+ this->left->hess_reverse_1_clear_index();
+ this->right->hess_reverse_1_clear_index();
+ this->Node::hess_reverse_1_clear_index();
+}
+
+unsigned int BinaryOPNode::hess_reverse_0()
+{
+ assert(this->left!=NULL && right!=NULL);
+ if(index==0)
+ {
+ unsigned int lindex=0, rindex=0;
+ lindex = left->hess_reverse_0();
+ rindex = right->hess_reverse_0();
+ assert(lindex!=0 && rindex !=0);
+ II->set(lindex);
+ II->set(rindex);
+ double rx,rx_bar,rw,rw_bar;
+ double lx,lx_bar,lw,lw_bar;
+ double x,x_bar,w,w_bar;
+ double r_dh, l_dh;
+ right->hess_reverse_0_get_values(rindex,rx,rx_bar,rw,rw_bar);
+ left->hess_reverse_0_get_values(lindex,lx,lx_bar,lw,lw_bar);
+ switch(op)
+ {
+ case OP_PLUS:
+ // cout<<"lindex="<<lindex<<"\trindex="<<rindex<<"\tI="<<I<<endl;
+ x = lx + rx;
+ // cout<<lx<<"\t+"<<rx<<"\t="<<x<<"\t\t"<<toString(0)<<endl;
+ x_bar = 0;
+ l_dh = 1;
+ r_dh = 1;
+ w = lw * l_dh + rw * r_dh;
+ // cout<<lw<<"\t+"<<rw<<"\t="<<w<<"\t\t"<<toString(0)<<endl;
+ w_bar = 0;
+ break;
+ case OP_MINUS:
+ x = lx - rx;
+ x_bar = 0;
+ l_dh = 1;
+ r_dh = -1;
+ w = lw * l_dh + rw * r_dh;
+ w_bar = 0;
+ break;
+ case OP_TIMES:
+ x = lx * rx;
+ x_bar = 0;
+ l_dh = rx;
+ r_dh = lx;
+ w = lw * l_dh + rw * r_dh;
+ w_bar = 0;
+ break;
+ case OP_DIVID:
+ x = lx / rx;
+ x_bar = 0;
+ l_dh = 1/rx;
+ r_dh = -lx/pow(rx,2);
+ w = lw * l_dh + rw * r_dh;
+ w_bar = 0;
+ break;
+ case OP_POW:
+ if(right->getType()==PNode_Type)
+ {
+ x = pow(lx,rx);
+ x_bar = 0;
+ l_dh = rx*pow(lx,(rx-1));
+ r_dh = 0;
+ w = lw * l_dh + rw * r_dh;
+ w_bar = 0;
+ }
+ else
+ {
+ assert(lx>0.0); //otherwise log(lx) undefined in real number
+ x = pow(lx,rx);
+ x_bar = 0;
+ l_dh = rx*pow(lx,(rx-1));
+ r_dh = pow(lx,rx)*log(lx); //log(lx) cause -inf when lx=0;
+ w = lw * l_dh + rw * r_dh;
+ w_bar = 0;
+ }
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented!"<<endl;
+ assert(false);
+ break;
+ }
+ TT->set(x);
+ TT->set(x_bar);
+ TT->set(w);
+ TT->set(w_bar);
+ TT->set(l_dh);
+ TT->set(r_dh);
+ assert(TT->index == TT->index);
+ index = TT->index;
+ }
+ return index;
+}
+
+void BinaryOPNode::hess_reverse_0_get_values(unsigned int i,double& x, double& x_bar, double& w, double& w_bar)
+{
+ --i; // skip the r_dh (ie, dh/du)
+ --i; // skip the l_dh (ie. dh/dv)
+ w_bar = TT->get(--i);
+ w = TT->get(--i);
+ x_bar = TT->get(--i);
+ x = TT->get(--i);
+}
+
+void BinaryOPNode::hess_reverse_1(unsigned int i)
+{
+ n_in_arcs--;
+ if(n_in_arcs==0)
+ {
+ assert(right!=NULL && left!=NULL);
+ unsigned int rindex = II->get(--(II->index));
+ unsigned int lindex = II->get(--(II->index));
+ // cout<<"ri["<<rindex<<"]\tli["<<lindex<<"]\t"<<this->toString(0)<<endl;
+ double r_dh = TT->get(--i);
+ double l_dh = TT->get(--i);
+ double w_bar = TT->get(--i);
+ --i; //skip w
+ double x_bar = TT->get(--i);
+ --i; //skip x
+
+ double lw_bar=0,rw_bar=0;
+ double lw=0,lx=0; left->hess_reverse_1_get_xw(lindex,lw,lx);
+ double rw=0,rx=0; right->hess_reverse_1_get_xw(rindex,rw,rx);
+ switch(op)
+ {
+ case OP_PLUS:
+ assert(l_dh==1);
+ assert(r_dh==1);
+ lw_bar += w_bar*l_dh;
+ rw_bar += w_bar*r_dh;
+ break;
+ case OP_MINUS:
+ assert(l_dh==1);
+ assert(r_dh==-1);
+ lw_bar += w_bar*l_dh;
+ rw_bar += w_bar*r_dh;
+ break;
+ case OP_TIMES:
+ assert(rx == l_dh);
+ assert(lx == r_dh);
+ lw_bar += w_bar*rx;
+ lw_bar += x_bar*lw*0 + x_bar*rw*1;
+ rw_bar += w_bar*lx;
+ rw_bar += x_bar*lw*1 + x_bar*rw*0;
+ break;
+ case OP_DIVID:
+ lw_bar += w_bar*l_dh;
+ lw_bar += x_bar*lw*0 + x_bar*rw*-1/(pow(rx,2));
+ rw_bar += w_bar*r_dh;
+ rw_bar += x_bar*lw*-1/pow(rx,2) + x_bar*rw*2*lx/pow(rx,3);
+ break;
+ case OP_POW:
+ if(right->getType()==PNode_Type){
+ lw_bar += w_bar*l_dh;
+ lw_bar += x_bar*lw*pow(lx,rx-2)*rx*(rx-1) + 0;
+ rw_bar += w_bar*r_dh; assert(r_dh==0.0);
+ rw_bar += 0;
+ }
+ else{
+ assert(lx>0.0); //otherwise log(lx) is not define in Real
+ lw_bar += w_bar*l_dh;
+ lw_bar += x_bar*lw*pow(lx,rx-2)*rx*(rx-1) + x_bar*rw*pow(lx,rx-1)*(rx*log(lx)+1); //cause log(lx)=-inf when
+ rw_bar += w_bar*r_dh;
+ rw_bar += x_bar*lw*pow(lx,rx-1)*(rx*log(lx)+1) + x_bar*rw*pow(lx,rx)*pow(log(lx),2);
+ }
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented !"<<endl;
+ assert(false);
+ break;
+ }
+ double rx_bar = x_bar*r_dh;
+ double lx_bar = x_bar*l_dh;
+ right->update_x_bar(rindex,rx_bar);
+ left->update_x_bar(lindex,lx_bar);
+ right->update_w_bar(rindex,rw_bar);
+ left->update_w_bar(lindex,lw_bar);
+
+
+ this->right->hess_reverse_1(rindex);
+ this->left->hess_reverse_1(lindex);
+ }
+}
+void BinaryOPNode::hess_reverse_1_init_x_bar(unsigned int i)
+{
+ TT->at(i-5) = 1;
+}
+void BinaryOPNode::update_x_bar(unsigned int i ,double v)
+{
+ TT->at(i-5) += v;
+}
+void BinaryOPNode::update_w_bar(unsigned int i ,double v)
+{
+ TT->at(i-3) += v;
+}
+void BinaryOPNode::hess_reverse_1_get_xw(unsigned int i,double& w,double& x)
+{
+ w = TT->get(i-4);
+ x = TT->get(i-6);
+}
+void BinaryOPNode::hess_reverse_get_x(unsigned int i,double& x)
+{
+ x = TT->get(i-6);
+}
+
+
+void BinaryOPNode::nonlinearEdges(EdgeSet& edges)
+{
+ for(list<Edge>::iterator it=edges.edges.begin();it!=edges.edges.end();)
+ {
+ Edge e = *it;
+ if(e.a==this || e.b == this){
+ if(e.a == this && e.b == this)
+ {
+ Edge e1(left,left);
+ Edge e2(right,right);
+ Edge e3(left,right);
+ edges.insertEdge(e1);
+ edges.insertEdge(e2);
+ edges.insertEdge(e3);
+ }
+ else
+ {
+ Node* o = e.a==this? e.b: e.a;
+ Edge e1(left,o);
+ Edge e2(right,o);
+ edges.insertEdge(e1);
+ edges.insertEdge(e2);
+ }
+ it = edges.edges.erase(it);
+ }
+ else
+ {
+ it++;
+ }
+ }
+
+ Edge e1(left,right);
+ Edge e2(left,left);
+ Edge e3(right,right);
+ switch(op)
+ {
+ case OP_PLUS:
+ case OP_MINUS:
+ //do nothing for linear operator
+ break;
+ case OP_TIMES:
+ edges.insertEdge(e1);
+ break;
+ case OP_DIVID:
+ edges.insertEdge(e1);
+ edges.insertEdge(e3);
+ break;
+ case OP_POW:
+ edges.insertEdge(e1);
+ edges.insertEdge(e2);
+ edges.insertEdge(e3);
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implmented !"<<endl;
+ assert(false);
+ break;
+ }
+ left->nonlinearEdges(edges);
+ right->nonlinearEdges(edges);
+}
+
+#if FORWARD_ENABLED
+
+void BinaryOPNode::hess_forward(unsigned int len, double** ret_vec)
+{
+ double* lvec = NULL;
+ double* rvec = NULL;
+ if(left!=NULL){
+ left->hess_forward(len,&lvec);
+ }
+ if(right!=NULL){
+ right->hess_forward(len,&rvec);
+ }
+
+ *ret_vec = new double[len];
+ hess_forward_calc0(len,lvec,rvec,*ret_vec);
+ //delete lvec, rvec
+ delete[] lvec;
+ delete[] rvec;
+}
+
+void BinaryOPNode::hess_forward_calc0(unsigned int& len, double* lvec, double* rvec, double* ret_vec)
+{
+ double hu = NaN_Double, hv= NaN_Double;
+ double lval = NaN_Double, rval = NaN_Double;
+ double val = NaN_Double;
+ unsigned int index = 0;
+ switch (op)
+ {
+ case OP_PLUS:
+ rval = SV->pop_back();
+ lval = SV->pop_back();
+ val = lval + rval;
+ SV->push_back(val);
+ //calculate the first order derivatives
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ ret_vec[i] = lvec[i]+rvec[i];
+ }
+ //calculate the second order
+ index = AutoDiff::num_var;
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ for(unsigned int j=i;j<AutoDiff::num_var;++j){
+ ret_vec[index] = lvec[index] + 0 + rvec[index] + 0;
+ ++index;
+ }
+ }
+ assert(index==len);
+ break;
+ case OP_MINUS:
+ rval = SV->pop_back();
+ lval = SV->pop_back();
+ val = lval + rval;
+ SV->push_back(val);
+ //calculate the first order derivatives
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ ret_vec[i] = lvec[i] - rvec[i];
+ }
+ //calculate the second order
+ index = AutoDiff::num_var;
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ for(unsigned int j=i;j<AutoDiff::num_var;++j){
+ ret_vec[index] = lvec[index] + 0 - rvec[index] + 0;
+ ++index;
+ }
+ }
+ assert(index==len);
+ break;
+ case OP_TIMES:
+ rval = SV->pop_back();
+ lval = SV->pop_back();
+ val = lval * rval;
+ SV->push_back(val);
+ hu = rval;
+ hv = lval;
+ //calculate the first order derivatives
+ for(unsigned int i =0;i<AutoDiff::num_var;++i)
+ {
+ ret_vec[i] = hu*lvec[i] + hv*rvec[i];
+ }
+ //calculate the second order
+ index = AutoDiff::num_var;
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ for(unsigned int j=i;j<AutoDiff::num_var;++j)
+ {
+ ret_vec[index] = hu * lvec[index] + lvec[i] * rvec[j]+hv * rvec[index] + rvec[i] * lvec[j];
+ ++index;
+ }
+ }
+ assert(index==len);
+ break;
+ case OP_POW:
+ rval = SV->pop_back();
+ lval = SV->pop_back();
+ val = pow(lval,rval);
+ SV->push_back(val);
+ if(left->getType()==PNode_Type && right->getType()==PNode_Type)
+ {
+ std::fill_n(ret_vec,len,0);
+ }
+ else
+ {
+ hu = rval*pow(lval,(rval-1));
+ hv = pow(lval,rval)*log(lval);
+ if(left->getType()==PNode_Type)
+ {
+ double coeff = pow(log(lval),2)*pow(lval,rval);
+ //calculate the first order derivatives
+ for(unsigned int i =0;i<AutoDiff::num_var;++i)
+ {
+ ret_vec[i] = hu*lvec[i] + hv*rvec[i];
+ }
+ //calculate the second order
+ index = AutoDiff::num_var;
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ for(unsigned int j=i;j<AutoDiff::num_var;++j)
+ {
+ ret_vec[index] = 0 + 0 + hv * rvec[index] + rvec[i] * coeff * rvec[j];
+ ++index;
+ }
+ }
+ }
+ else if(right->getType()==PNode_Type)
+ {
+ double coeff = rval*(rval-1)*pow(lval,rval-2);
+ //calculate the first order derivatives
+ for(unsigned int i =0;i<AutoDiff::num_var;++i)
+ {
+ ret_vec[i] = hu*lvec[i] + hv*rvec[i];
+ }
+ //calculate the second order
+ index = AutoDiff::num_var;
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ for(unsigned int j=i;j<AutoDiff::num_var;++j)
+ {
+ ret_vec[index] = hu*lvec[index] + lvec[i] * coeff * lvec[j] + 0 + 0;
+ ++index;
+ }
+ }
+ }
+ else
+ {
+ assert(false);
+ }
+ }
+ assert(index==len);
+ break;
+ case OP_SIN: //TODO should move to UnaryOPNode.cpp?
+ assert(left!=NULL&&right==NULL);
+ lval = SV->pop_back();
+ val = sin(lval);
+ SV->push_back(val);
+ hu = cos(lval);
+
+ double coeff;
+ coeff = -val; //=sin(left->val); -- and avoid cross initialisation
+ //calculate the first order derivatives
+ for(unsigned int i =0;i<AutoDiff::num_var;++i)
+ {
+ ret_vec[i] = hu*lvec[i] + 0;
+ }
+ //calculate the second order
+ index = AutoDiff::num_var;
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ for(unsigned int j=i;j<AutoDiff::num_var;++j)
+ {
+ ret_vec[index] = hu*lvec[index] + lvec[i] * coeff * lvec[j] + 0 + 0;
+ ++index;
+ }
+ }
+ assert(index==len);
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented!";
+ break;
+ }
+}
+#endif
+
+
+string BinaryOPNode::toString(int level){
+ ostringstream oss;
+ string s(level,'\t');
+ oss<<s<<"[BinaryOPNode]("<<op<<")";
+ return oss.str();
+}
+
+} /* namespace AutoDiff */
diff --git a/src/boost/libs/yap/example/autodiff_library/BinaryOPNode.h b/src/boost/libs/yap/example/autodiff_library/BinaryOPNode.h
new file mode 100644
index 00000000..7abc702a
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/BinaryOPNode.h
@@ -0,0 +1,57 @@
+/*
+ * BinaryOPNode.h
+ *
+ * Created on: 6 Nov 2013
+ * Author: s0965328
+ */
+
+#ifndef BINARYOPNODE_H_
+#define BINARYOPNODE_H_
+
+#include "OPNode.h"
+
+namespace AutoDiff {
+
+class EdgeSet;
+
+class BinaryOPNode: public OPNode {
+public:
+
+ static OPNode* createBinaryOpNode(OPCODE op, Node* left, Node* right);
+ virtual ~BinaryOPNode();
+
+ void collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total);
+ void eval_function();
+
+ void grad_reverse_0();
+ void grad_reverse_1();
+
+ void hess_forward(unsigned int len, double** ret_vec);
+
+ unsigned int hess_reverse_0();
+ void hess_reverse_0_init_n_in_arcs();
+ void hess_reverse_0_get_values(unsigned int,double&, double&, double&, double&);
+ void hess_reverse_1(unsigned int i);
+ void hess_reverse_1_init_x_bar(unsigned int);
+ void update_x_bar(unsigned int,double);
+ void update_w_bar(unsigned int,double);
+ void hess_reverse_1_get_xw(unsigned int, double&,double&);
+ void hess_reverse_get_x(unsigned int,double& x);
+ void hess_reverse_1_clear_index();
+
+ void nonlinearEdges(EdgeSet& a);
+
+ void inorder_visit(int level,ostream& oss);
+ string toString(int level);
+
+ Node* right;
+
+private:
+ BinaryOPNode(OPCODE op, Node* left, Node* right);
+ void calc_eval_function();
+ void calc_grad_reverse_0();
+ void hess_forward_calc0(unsigned int& len, double* lvec, double* rvec,double* ret_vec);
+};
+
+} /* namespace AutoDiff */
+#endif /* BINARYOPNODE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/Edge.cpp b/src/boost/libs/yap/example/autodiff_library/Edge.cpp
new file mode 100644
index 00000000..4a7183b6
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Edge.cpp
@@ -0,0 +1,54 @@
+/*
+ * Edge.cpp
+ *
+ * Created on: 12 Nov 2013
+ * Author: s0965328
+ */
+
+#include "Edge.h"
+#include <iostream>
+#include <sstream>
+
+namespace AutoDiff {
+
+Edge::Edge(Node* a_,Node* b_):a(a_),b(b_) {
+
+}
+
+Edge::~Edge() {
+ a = NULL;
+ b = NULL;
+}
+
+Edge::Edge(const Edge& e)
+{
+ a = e.a;
+ b = e.b;
+}
+
+bool Edge::isEqual(Edge* e)
+{
+ if(e->a == a && e->b == b)
+ {
+ return true;
+ }
+ else if(e->b == a && e->a == b)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool Edge::isEqual(Edge& e)
+{
+ return isEqual(&e);
+}
+
+string Edge::toString()
+{
+ ostringstream oss;
+ oss<<""<<a->toString(0)<<"|"<<a<<" ----- "<<b->toString(0)<<"|"<<b<<""<<endl;
+ return oss.str();
+}
+
+} /* namespace AutoDiff */
diff --git a/src/boost/libs/yap/example/autodiff_library/Edge.h b/src/boost/libs/yap/example/autodiff_library/Edge.h
new file mode 100644
index 00000000..10126ac2
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Edge.h
@@ -0,0 +1,33 @@
+/*
+ * Edge.h
+ *
+ * Created on: 12 Nov 2013
+ * Author: s0965328
+ */
+
+#ifndef EDGE_H_
+#define EDGE_H_
+
+
+#include "Node.h"
+
+namespace AutoDiff {
+
+class Edge {
+public:
+ Edge(Node* a, Node* b);
+ Edge(const Edge& e);
+ virtual ~Edge();
+
+ bool isEqual(Edge*);
+ bool isEqual(Edge&);
+ std::string toString();
+
+ Node* a;
+ Node* b;
+
+
+};
+
+} /* namespace AutoDiff */
+#endif /* EDGE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/EdgeSet.cpp b/src/boost/libs/yap/example/autodiff_library/EdgeSet.cpp
new file mode 100644
index 00000000..20e16132
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/EdgeSet.cpp
@@ -0,0 +1,76 @@
+/*
+ * EdgeSet.cpp
+ *
+ * Created on: 12 Nov 2013
+ * Author: s0965328
+ */
+
+#include "EdgeSet.h"
+#include "Edge.h"
+#include <sstream>
+
+using namespace std;
+namespace AutoDiff {
+
+EdgeSet::EdgeSet() {
+ // TODO Auto-generated constructor stub
+
+}
+
+EdgeSet::~EdgeSet() {
+ edges.clear();
+}
+
+bool EdgeSet::containsEdge(Edge& e)
+{
+ list<Edge>::iterator it = edges.begin();
+ for(;it!= edges.end();it++){
+ Edge eit = *it;
+ if(eit.isEqual(e))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void EdgeSet::insertEdge(Edge& e) {
+ if(!containsEdge(e)){
+ edges.push_front(e);
+ }
+}
+
+void EdgeSet::clear() {
+ edges.clear();
+}
+
+unsigned int EdgeSet::size(){
+ return edges.size();
+}
+
+unsigned int EdgeSet::numSelfEdges(){
+ unsigned int diag = 0;
+ list<Edge>::iterator it = edges.begin();
+ for(;it!=edges.end();it++)
+ {
+ Edge eit = *it;
+ if(eit.a == eit.b)
+ {
+ diag++;
+ }
+ }
+ return diag;
+}
+
+string EdgeSet::toString()
+{
+ ostringstream oss;
+ list<Edge>::iterator it = edges.begin();
+ for(;it!=edges.end();it++)
+ {
+ oss<<(*it).toString()<<endl;
+ }
+ return oss.str();
+}
+
+} /* namespace AutoDiff */
diff --git a/src/boost/libs/yap/example/autodiff_library/EdgeSet.h b/src/boost/libs/yap/example/autodiff_library/EdgeSet.h
new file mode 100644
index 00000000..26b2be12
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/EdgeSet.h
@@ -0,0 +1,33 @@
+/*
+ * EdgeSet.h
+ *
+ * Created on: 12 Nov 2013
+ * Author: s0965328
+ */
+
+#ifndef EDGESET_H_
+#define EDGESET_H_
+
+#include "Edge.h"
+#include <list>
+
+namespace AutoDiff {
+
+class EdgeSet {
+public:
+ EdgeSet();
+ virtual ~EdgeSet();
+
+ void insertEdge(Edge& e);
+ bool containsEdge(Edge& e);
+ unsigned int numSelfEdges();
+ void clear();
+ unsigned int size();
+ std::string toString();
+
+
+ std::list<Edge> edges;
+};
+
+} /* namespace AutoDiff */
+#endif /* EDGESET_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/LICENSE b/src/boost/libs/yap/example/autodiff_library/LICENSE
new file mode 100644
index 00000000..f09534cf
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 fqiang
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/src/boost/libs/yap/example/autodiff_library/Node.cpp b/src/boost/libs/yap/example/autodiff_library/Node.cpp
new file mode 100644
index 00000000..13ed5764
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Node.cpp
@@ -0,0 +1,32 @@
+/*
+ * Node.cpp
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#include "Node.h"
+
+namespace AutoDiff {
+
+unsigned int Node::DEFAULT_INDEX = 0;
+Node::Node():index(Node::DEFAULT_INDEX),n_in_arcs(0){
+}
+
+
+Node::~Node() {
+}
+
+void Node::hess_reverse_0_init_n_in_arcs()
+{
+ n_in_arcs++;
+// cout<<this->toString(0)<<endl;
+}
+
+void Node::hess_reverse_1_clear_index()
+{
+ index = Node::DEFAULT_INDEX;
+}
+
+}
+
diff --git a/src/boost/libs/yap/example/autodiff_library/Node.h b/src/boost/libs/yap/example/autodiff_library/Node.h
new file mode 100644
index 00000000..f89c2bb1
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Node.h
@@ -0,0 +1,65 @@
+/*
+ * Node.h
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef NODE_H_
+#define NODE_H_
+
+#include <boost/unordered_set.hpp>
+#include "auto_diff_types.h"
+
+using namespace std;
+
+namespace AutoDiff {
+
+class EdgeSet;
+
+class Node {
+public:
+ Node();
+ virtual ~Node();
+
+ virtual void eval_function() = 0;
+ virtual void grad_reverse_0() = 0;
+ virtual void grad_reverse_1_init_adj() = 0;
+ virtual void grad_reverse_1() = 0;
+ virtual void update_adj(double& v) = 0;
+ virtual unsigned int hess_reverse_0() = 0;
+ virtual void hess_reverse_0_init_n_in_arcs();
+ virtual void hess_reverse_0_get_values(unsigned int,double&, double&,double&, double&) = 0;
+ virtual void hess_reverse_1(unsigned int i) = 0;
+ virtual void hess_reverse_1_init_x_bar(unsigned int) = 0;
+ virtual void update_x_bar(unsigned int,double) = 0;
+ virtual void update_w_bar(unsigned int,double) = 0;
+ virtual void hess_reverse_1_get_xw(unsigned int, double&,double&) = 0;
+ virtual void hess_reverse_get_x(unsigned int,double& x)=0;
+ virtual void hess_reverse_1_clear_index();
+ //routing for checking non-zero structures
+ virtual void collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total) = 0;
+ virtual void nonlinearEdges(EdgeSet&) = 0;
+#if FORWARD_ENABLED
+ virtual void hess_forward(unsigned int len, double** ret_vec) = 0;
+#endif
+
+ //other utility methods
+ virtual void inorder_visit( int level,ostream& oss) = 0;
+ virtual string toString(int levl) = 0;
+ virtual TYPE getType() = 0;
+
+
+ //! index on the tape
+ unsigned int index;
+ //! number of incoming arcs
+ //! n_in_arcs in root node equals 1 before evaluation and 0 after evaluation
+ unsigned int n_in_arcs;
+
+ static unsigned int DEFAULT_INDEX;
+
+};
+
+} // end namespace foo
+
+#endif /* NODE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/OPNode.cpp b/src/boost/libs/yap/example/autodiff_library/OPNode.cpp
new file mode 100644
index 00000000..0f647931
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/OPNode.cpp
@@ -0,0 +1,37 @@
+/*
+ * OpNode.cpp
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#include "OPNode.h"
+#include "Stack.h"
+#include "Tape.h"
+#include "PNode.h"
+/***********************************************************
+ h
+ / \
+ u v ----- hu hv represent dh/du dh/dv resepectively.
+ - - -
+ x1....xn
+***********************************************************/
+
+namespace AutoDiff{
+
+OPNode::OPNode(OPCODE op, Node* left) : ActNode(), op(op), left(left),val(NaN_Double) {
+}
+
+TYPE OPNode::getType()
+{
+ return OPNode_Type;
+}
+
+OPNode::~OPNode() {
+ if(left->getType()!=VNode_Type)
+ {
+ delete left;
+ this->left = NULL;
+ }
+}
+}
diff --git a/src/boost/libs/yap/example/autodiff_library/OPNode.h b/src/boost/libs/yap/example/autodiff_library/OPNode.h
new file mode 100644
index 00000000..e5ed2da9
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/OPNode.h
@@ -0,0 +1,37 @@
+/*
+ * OpNode.h
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef OPNODE_H_
+#define OPNODE_H_
+
+#include "Node.h"
+#include "ActNode.h"
+
+namespace AutoDiff {
+
+using namespace std;
+
+class OPNode: public ActNode {
+public:
+ OPNode(OPCODE op,Node* left);
+ virtual ~OPNode();
+
+ TYPE getType();
+
+ OPCODE op;
+ Node* left;
+ double val;
+
+
+
+private:
+
+};
+
+}
+
+#endif /* OPNODE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/PNode.cpp b/src/boost/libs/yap/example/autodiff_library/PNode.cpp
new file mode 100644
index 00000000..ee07a1f2
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/PNode.cpp
@@ -0,0 +1,147 @@
+/*
+ * PNode.cpp
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#include "PNode.h"
+#include "Stack.h"
+#include "Tape.h"
+#include "EdgeSet.h"
+
+namespace AutoDiff {
+
+PNode::PNode(double value):pval(value) {
+ assert(!isnan(value));
+}
+
+PNode::~PNode() {
+}
+
+void PNode::inorder_visit(int level,ostream& oss){
+ oss<<this->toString(level)<<endl;
+}
+
+void PNode::collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total)
+{
+ //do not fill this to nodes, as this is a parameter node
+ total++;
+}
+
+void PNode::eval_function()
+{
+ SV->push_back(pval);
+}
+
+string PNode::toString(int level)
+{
+ ostringstream oss;
+ string s(level,'\t');
+ oss<<s<<"[PNode]("<<pval<<")";
+ return oss.str();
+}
+
+void PNode::grad_reverse_0()
+{
+ SV->push_back(pval);
+}
+void PNode::grad_reverse_1_init_adj()
+{
+ //do nothing as PNode does not have adjoint
+}
+
+void PNode::grad_reverse_1()
+{
+ //do nothing
+ //this is a parameter
+}
+
+void PNode::update_adj(double& v)
+{
+ //do nothing
+ //no adj for PNode
+}
+
+unsigned int PNode::hess_reverse_0()
+{
+ if(index==0)
+ {
+ TT->set(pval);
+ assert(TT->index == TT->index);
+ index = TT->index;
+ }
+ return index;
+}
+
+void PNode::hess_reverse_0_get_values(unsigned int i,double& x,double& x_bar,double& w,double& w_bar)
+{
+ x = TT->get(--i);
+ x_bar = 0;
+ w = 0;
+ w_bar = 0;
+}
+
+void PNode::hess_reverse_1(unsigned int i)
+{
+ n_in_arcs--;
+ //leaf node do nothing
+}
+
+void PNode::hess_reverse_1_init_x_bar(unsigned int)
+{
+ //do nothing as Parameter does not have x_bar
+}
+
+void PNode::update_x_bar(unsigned int i ,double v)
+{
+ //do nothing as Parameter does not have x_bar
+}
+void PNode::update_w_bar(unsigned int i ,double v)
+{
+ //do nothing as Parameter does not have w_bar
+}
+void PNode::hess_reverse_1_get_xw(unsigned int i, double& w,double& x)
+{
+ //do nothing as Parameter does not have w
+ x = TT->get(i-1);
+ w = 0;
+}
+void PNode::hess_reverse_get_x(unsigned int i, double& x)
+{
+ x = TT->get(i-1);
+}
+
+void PNode::nonlinearEdges(EdgeSet& edges)
+{
+ for(std::list<Edge>::iterator it=edges.edges.begin();it!=edges.edges.end();)
+ {
+ Edge e = *it;
+ if(e.a == this || e.b == this)
+ {
+ it = edges.edges.erase(it); //erase invalidate the iterator
+ }
+ else
+ {
+ it++;
+ }
+ }
+}
+
+#if FORWARD_ENABLED
+void PNode::hess_forward(unsigned int len, double** ret_vec)
+{
+ //it's a scalar
+ (*ret_vec) = new double[len];
+ std::fill_n(*ret_vec,len,0);
+ SV->push_back(this->pval);
+ assert(SV->size()==1);
+}
+#endif
+
+
+TYPE PNode::getType()
+{
+ return PNode_Type;
+}
+}
diff --git a/src/boost/libs/yap/example/autodiff_library/PNode.h b/src/boost/libs/yap/example/autodiff_library/PNode.h
new file mode 100644
index 00000000..58924d64
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/PNode.h
@@ -0,0 +1,47 @@
+/*
+ * PNode.h
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef PNODE_H_
+#define PNODE_H_
+
+#include "Node.h"
+namespace AutoDiff {
+
+using namespace std;
+class PNode: public Node {
+public:
+ PNode(double value);
+ virtual ~PNode();
+ void collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total);
+ void eval_function();
+ void grad_reverse_0();
+ void grad_reverse_1_init_adj();
+ void grad_reverse_1();
+ void update_adj(double& v);
+ void hess_forward(unsigned int len,double** ret_vec);
+ unsigned int hess_reverse_0();
+ void hess_reverse_0_get_values(unsigned int i,double& x,double& x_bar,double& w,double& w_bar);
+ void hess_reverse_1(unsigned int i);
+ void hess_reverse_1_init_x_bar(unsigned int);
+ void update_x_bar(unsigned int, double);
+ void update_w_bar(unsigned int, double);
+ void hess_reverse_1_get_xw(unsigned int, double&,double&);
+ void hess_reverse_get_x(unsigned int,double& x);
+
+ void nonlinearEdges(EdgeSet&);
+
+ void inorder_visit(int level,ostream& oss);
+ string toString(int level);
+ TYPE getType();
+
+ double pval;
+
+};
+
+} // end namespace foo
+
+#endif /* PNODE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/README.md b/src/boost/libs/yap/example/autodiff_library/README.md
new file mode 100644
index 00000000..8f375446
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/README.md
@@ -0,0 +1,10 @@
+autodiff_library
+================ <\br>
+
+Automatic Differentiation Library <br>
+1. Very easy access and light weight c++/c library <br>
+2. Build computation graph as a DAG. <br>
+3. Provide function evaluation, reverse gradient, reverse Hessian-vector, forward Hessian computation calls.<br>
+4. State-of-the-art Object-Oriented Design and Implementation in C++ <br>
+5. A modified version of this library is integrated into the Parallel Structured Model Generator(PSMG)--an algebraic modelling langauge for Mathematical Programming.
+See project wiki for more detail.
diff --git a/src/boost/libs/yap/example/autodiff_library/Stack.cpp b/src/boost/libs/yap/example/autodiff_library/Stack.cpp
new file mode 100644
index 00000000..f0e69f84
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Stack.cpp
@@ -0,0 +1,58 @@
+/*
+ * Stack.cpp
+ *
+ * Created on: 15 Apr 2013
+ * Author: s0965328
+ */
+
+
+#include <cstddef>
+#include <math.h>
+#include <cassert>
+
+#include "Stack.h"
+
+namespace AutoDiff {
+
+
+Stack* Stack::vals = NULL;
+Stack* Stack::diff = NULL;
+
+Stack::Stack()
+{
+}
+
+Stack::~Stack() {
+ this->clear();
+}
+
+
+double Stack::pop_back()
+{
+ assert(this->lifo.size()!=0);
+ double v = this->lifo.top();
+ lifo.pop();
+ return v;
+}
+void Stack::push_back(double& v)
+{
+ assert(!isnan(v));
+ this->lifo.push(v);
+}
+double& Stack::peek()
+{
+ return this->lifo.top();
+}
+unsigned int Stack::size()
+{
+ return this->lifo.size();
+}
+
+void Stack::clear()
+{
+ while(!this->lifo.empty())
+ {
+ this->lifo.pop();
+ }
+}
+}
diff --git a/src/boost/libs/yap/example/autodiff_library/Stack.h b/src/boost/libs/yap/example/autodiff_library/Stack.h
new file mode 100644
index 00000000..30f5a3f0
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Stack.h
@@ -0,0 +1,38 @@
+/*
+ * Stack.h
+ *
+ * Created on: 15 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef STACK_H_
+#define STACK_H_
+
+#include <stack>
+
+namespace AutoDiff {
+
+using namespace std;
+#define SV (Stack::vals)
+#define SD (Stack::diff)
+
+class Stack {
+public:
+ Stack();
+ double pop_back();
+ void push_back(double& v);
+ double& peek();
+ unsigned int size();
+ void clear();
+ virtual ~Stack();
+
+ stack<double> lifo;
+
+ static Stack* diff;
+ static Stack* vals;
+
+
+};
+
+}
+#endif /* STACK_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/Tape.cpp b/src/boost/libs/yap/example/autodiff_library/Tape.cpp
new file mode 100644
index 00000000..0a5682f3
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Tape.cpp
@@ -0,0 +1,16 @@
+/*
+ * Tape.cpp
+ *
+ * Created on: 6 Nov 2013
+ * Author: s0965328
+ */
+
+
+
+#include "Tape.h"
+
+namespace AutoDiff
+{
+ template<> Tape<unsigned int>* Tape<unsigned int>::indexTape = NULL;
+ template<> Tape<double>* Tape<double>::valueTape = NULL;
+}
diff --git a/src/boost/libs/yap/example/autodiff_library/Tape.h b/src/boost/libs/yap/example/autodiff_library/Tape.h
new file mode 100644
index 00000000..9ca62c4d
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/Tape.h
@@ -0,0 +1,97 @@
+/*
+ * Tape.h
+ *
+ * Created on: 15 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef TAPE_H_
+#define TAPE_H_
+
+#include <vector>
+#include <string>
+#include <cassert>
+#include <sstream>
+#include <iostream>
+
+
+namespace AutoDiff {
+
+using namespace std;
+#define TT (Tape<double>::valueTape)
+#define II (Tape<unsigned int>::indexTape)
+
+template<typename T> class Tape {
+public:
+ Tape<T> () : index(0){};
+ T& at(const unsigned int index);
+ const T& get(const unsigned int index);
+ void set(T& v);
+ unsigned int size();
+ void clear();
+ bool empty();
+ string toString();
+ virtual ~Tape();
+
+ vector<T> vals;
+ unsigned int index;
+
+ static Tape<double>* valueTape;
+ static Tape<unsigned int>* indexTape;
+};
+
+
+template<typename T> Tape<T>::~Tape<T>()
+{
+ index = 0;
+ vals.clear();
+}
+
+template<typename T> T& Tape<T>::at(const unsigned int i)
+{
+ assert(this->vals.size()>i);
+ return vals[i];
+}
+template<typename T> const T& Tape<T>::get(const unsigned int i)
+{
+ assert(this->vals.size()>i);
+ return vals[i];
+}
+template <typename T> void Tape<T>::set(T& v)
+{
+ vals.push_back(v);
+ index++;
+}
+
+template<typename T> unsigned int Tape<T>::size()
+{
+ return this->vals.size();
+}
+
+template<typename T> bool Tape<T>::empty()
+{
+ return vals.empty();
+}
+
+template<typename T> void Tape<T>::clear()
+{
+ this->vals.clear();
+ this->index = 0;
+ assert(this->vals.size()==0);
+ assert(this->vals.empty());
+}
+
+template<typename T> string Tape<T>::toString()
+{
+ assert(vals.size()>=index);
+ ostringstream oss;
+ oss<<"Tape size["<<vals.size()<<"]";
+ for(unsigned int i=0;i<vals.size();i++){
+ if(i%10==0) oss<<endl;
+ oss<<vals[i]<<",";
+ }
+ oss<<endl;
+ return oss.str();
+}
+}
+#endif /* TAPE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/UaryOPNode.cpp b/src/boost/libs/yap/example/autodiff_library/UaryOPNode.cpp
new file mode 100644
index 00000000..73e2711c
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/UaryOPNode.cpp
@@ -0,0 +1,375 @@
+/*
+ * UaryOPNode.cpp
+ *
+ * Created on: 6 Nov 2013
+ * Author: s0965328
+ */
+
+#include "UaryOPNode.h"
+#include "BinaryOPNode.h"
+#include "PNode.h"
+#include "Stack.h"
+#include "Tape.h"
+#include "Edge.h"
+#include "EdgeSet.h"
+#include "auto_diff_types.h"
+
+#include <list>
+
+using namespace std;
+
+namespace AutoDiff {
+
+UaryOPNode::UaryOPNode(OPCODE op_, Node* left): OPNode(op_,left) {
+}
+
+OPNode* UaryOPNode::createUnaryOpNode(OPCODE op, Node* left)
+{
+ assert(left!=NULL);
+ OPNode* node = NULL;
+ if(op == OP_SQRT)
+ {
+ double param = 0.5;
+ node = BinaryOPNode::createBinaryOpNode(OP_POW,left,new PNode(param));
+ }
+ else if(op == OP_NEG)
+ {
+ double param = -1;
+ node = BinaryOPNode::createBinaryOpNode(OP_TIMES,left,new PNode(param));
+ }
+ else
+ {
+ node = new UaryOPNode(op,left);
+ }
+ return node;
+}
+
+UaryOPNode::~UaryOPNode() {
+
+}
+
+
+void UaryOPNode::inorder_visit(int level,ostream& oss){
+ if(left!=NULL){
+ left->inorder_visit(level+1,oss);
+ }
+ oss<<this->toString(level)<<endl;
+}
+
+void UaryOPNode::collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total)
+{
+ total++;
+ if(left!=NULL){
+ left->collect_vnodes(nodes,total);
+ }
+}
+
+void UaryOPNode::eval_function()
+{
+ if(left!=NULL){
+ left->eval_function();
+ }
+ this->calc_eval_function();
+}
+
+//1. visiting left if not NULL
+//2. then, visiting right if not NULL
+//3. calculating the immediate derivative hu and hv
+void UaryOPNode::grad_reverse_0(){
+ assert(left!=NULL);
+ this->adj = 0;
+ left->grad_reverse_0();
+ this->calc_grad_reverse_0();
+}
+
+//right left - right most traversal
+void UaryOPNode::grad_reverse_1()
+{
+ assert(left!=NULL);
+ double l_adj = SD->pop_back()*this->adj;
+ left->update_adj(l_adj);
+ left->grad_reverse_1();
+}
+
+void UaryOPNode::calc_grad_reverse_0()
+{
+ assert(left!=NULL);
+ double hu = NaN_Double;
+ double lval = SV->pop_back();
+ double val = NaN_Double;
+ switch (op)
+ {
+ case OP_SIN:
+ val = sin(lval);
+ hu = cos(lval);
+ break;
+ case OP_COS:
+ val = cos(lval);
+ hu = -sin(lval);
+ break;
+ default:
+ cerr<<"error op not impl"<<endl;
+ break;
+ }
+ SV->push_back(val);
+ SD->push_back(hu);
+}
+
+void UaryOPNode::calc_eval_function()
+{
+ double lval = SV->pop_back();
+ double val = NaN_Double;
+ switch (op)
+ {
+ case OP_SIN:
+ assert(left!=NULL);
+ val = sin(lval);
+ break;
+ case OP_COS:
+ assert(left!=NULL);
+ val = cos(lval);
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented!!"<<endl;
+ assert(false);
+ break;
+ }
+ SV->push_back(val);
+}
+
+void UaryOPNode::hess_reverse_0_init_n_in_arcs()
+{
+ this->left->hess_reverse_0_init_n_in_arcs();
+ this->Node::hess_reverse_0_init_n_in_arcs();
+}
+
+void UaryOPNode::hess_reverse_1_clear_index()
+{
+ this->left->hess_reverse_1_clear_index();
+ this->Node::hess_reverse_1_clear_index();
+}
+
+unsigned int UaryOPNode::hess_reverse_0()
+{
+ assert(left!=NULL);
+ if(index==0)
+ {
+ unsigned int lindex=0;
+ lindex = left->hess_reverse_0();
+ assert(lindex!=0);
+ II->set(lindex);
+ double lx,lx_bar,lw,lw_bar;
+ double x,x_bar,w,w_bar;
+ double l_dh;
+ switch(op)
+ {
+ case OP_SIN:
+ assert(left != NULL);
+ left->hess_reverse_0_get_values(lindex,lx,lx_bar,lw,lw_bar);
+ x = sin(lx);
+ x_bar = 0;
+ l_dh = cos(lx);
+ w = lw*l_dh;
+ w_bar = 0;
+ break;
+ case OP_COS:
+ assert(left!=NULL);
+ left->hess_reverse_0_get_values(lindex,lx,lx_bar,lw,lw_bar);
+ x = cos(lx);
+ x_bar = 0;
+ l_dh = -sin(lx);
+ w = lw*l_dh;
+ w_bar = 0;
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented!"<<endl;
+ assert(false);
+ break;
+ }
+ TT->set(x);
+ TT->set(x_bar);
+ TT->set(w);
+ TT->set(w_bar);
+ TT->set(l_dh);
+ assert(TT->index == TT->index);
+ index = TT->index;
+ }
+ return index;
+}
+
+void UaryOPNode::hess_reverse_0_get_values(unsigned int i,double& x, double& x_bar, double& w, double& w_bar)
+{
+ --i; // skip the l_dh (ie, dh/du)
+ w_bar = TT->get(--i);
+ w = TT->get(--i);
+ x_bar = TT->get(--i);
+ x = TT->get(--i);
+}
+
+void UaryOPNode::hess_reverse_1(unsigned int i)
+{
+ n_in_arcs--;
+ if(n_in_arcs==0)
+ {
+ double lindex = II->get(--(II->index));
+ // cout<<"li["<<lindex<<"]\t"<<this->toString(0)<<endl;
+ double l_dh = TT->get(--i);
+ double w_bar = TT->get(--i);
+ --i; //skip w
+ double x_bar = TT->get(--i);
+ --i; //skip x
+ // cout<<"i["<<i<<"]"<<endl;
+
+ assert(left!=NULL);
+ left->update_x_bar(lindex,x_bar*l_dh);
+ double lw_bar = 0;
+ double lw = 0,lx = 0;
+ left->hess_reverse_1_get_xw(lindex,lw,lx);
+ switch(op)
+ {
+ case OP_SIN:
+ assert(l_dh == cos(lx));
+ lw_bar += w_bar*l_dh;
+ lw_bar += x_bar*lw*(-sin(lx));
+ break;
+ case OP_COS:
+ assert(l_dh == -sin(lx));
+ lw_bar += w_bar*l_dh;
+ lw_bar += x_bar*lw*(-cos(lx));
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented!"<<endl;
+ break;
+ }
+ left->update_w_bar(lindex,lw_bar);
+ left->hess_reverse_1(lindex);
+ }
+}
+
+void UaryOPNode::hess_reverse_1_init_x_bar(unsigned int i)
+{
+ TT->at(i-4) = 1;
+}
+
+void UaryOPNode::update_x_bar(unsigned int i ,double v)
+{
+ TT->at(i-4) += v;
+}
+void UaryOPNode::update_w_bar(unsigned int i ,double v)
+{
+ TT->at(i-2) += v;
+}
+void UaryOPNode::hess_reverse_1_get_xw(unsigned int i,double& w,double& x)
+{
+ w = TT->get(i-3);
+ x = TT->get(i-5);
+}
+void UaryOPNode::hess_reverse_get_x(unsigned int i, double& x)
+{
+ x = TT->get(i-5);
+}
+
+void UaryOPNode::nonlinearEdges(EdgeSet& edges)
+{
+ for(list<Edge>::iterator it=edges.edges.begin();it!=edges.edges.end();)
+ {
+ Edge& e = *it;
+ if(e.a == this || e.b == this){
+ if(e.a == this && e.b == this)
+ {
+ Edge e1(left,left);
+ edges.insertEdge(e1);
+ }
+ else{
+ Node* o = e.a==this?e.b:e.a;
+ Edge e1(left,o);
+ edges.insertEdge(e1);
+ }
+ it = edges.edges.erase(it);
+ }
+ else
+ {
+ it++;
+ }
+ }
+
+ Edge e1(left,left);
+ switch(op)
+ {
+ case OP_SIN:
+ edges.insertEdge(e1);
+ break;
+ case OP_COS:
+ edges.insertEdge(e1);
+ break;
+ default:
+ cerr<<"op["<<op<<"] is not yet implemented !"<<endl;
+ assert(false);
+ break;
+ }
+ left->nonlinearEdges(edges);
+}
+
+#if FORWARD_ENABLED
+void UaryOPNode::hess_forward(unsigned int len, double** ret_vec)
+{
+ double* lvec = NULL;
+ if(left!=NULL){
+ left->hess_forward(len,&lvec);
+ }
+
+ *ret_vec = new double[len];
+ this->hess_forward_calc0(len,lvec,*ret_vec);
+ delete[] lvec;
+}
+
+void UaryOPNode::hess_forward_calc0(unsigned int& len, double* lvec, double* ret_vec)
+{
+ double hu = NaN_Double;
+ double lval = NaN_Double;
+ double val = NaN_Double;
+ unsigned int index = 0;
+ switch (op)
+ {
+ case OP_SIN:
+ assert(left!=NULL);
+ lval = SV->pop_back();
+ val = sin(lval);
+ SV->push_back(val);
+ hu = cos(lval);
+
+ double coeff;
+ coeff = -val; //=sin(left->val); -- and avoid cross initialisation
+ //calculate the first order derivatives
+ for(unsigned int i =0;i<AutoDiff::num_var;++i)
+ {
+ ret_vec[i] = hu*lvec[i] + 0;
+ }
+ //calculate the second order
+ index = AutoDiff::num_var;
+ for(unsigned int i=0;i<AutoDiff::num_var;++i)
+ {
+ for(unsigned int j=i;j<AutoDiff::num_var;++j)
+ {
+ ret_vec[index] = hu*lvec[index] + lvec[i] * coeff * lvec[j] + 0 + 0;
+ ++index;
+ }
+ }
+ assert(index==len);
+ break;
+ default:
+ cerr<<"op["<<op<<"] not yet implemented!";
+ break;
+ }
+}
+#endif
+
+string UaryOPNode::toString(int level)
+{
+ ostringstream oss;
+ string s(level,'\t');
+ oss<<s<<"[UaryOPNode]("<<op<<")";
+ return oss.str();
+}
+
+} /* namespace AutoDiff */
diff --git a/src/boost/libs/yap/example/autodiff_library/UaryOPNode.h b/src/boost/libs/yap/example/autodiff_library/UaryOPNode.h
new file mode 100644
index 00000000..241cd992
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/UaryOPNode.h
@@ -0,0 +1,52 @@
+/*
+ * UaryOPNode.h
+ *
+ * Created on: 6 Nov 2013
+ * Author: s0965328
+ */
+
+#ifndef UARYOPNODE_H_
+#define UARYOPNODE_H_
+
+#include "OPNode.h"
+
+namespace AutoDiff {
+
+class UaryOPNode: public OPNode {
+public:
+ static OPNode* createUnaryOpNode(OPCODE op, Node* left);
+ virtual ~UaryOPNode();
+
+ void inorder_visit(int level,ostream& oss);
+ void collect_vnodes(boost::unordered_set<Node*> & nodes,unsigned int& total);
+ void eval_function();
+
+ void grad_reverse_0();
+ void grad_reverse_1();
+#if FORWARD_ENABLED
+ void hess_forward(unsigned int len, double** ret_vec);
+#endif
+ unsigned int hess_reverse_0();
+ void hess_reverse_0_init_n_in_arcs();
+ void hess_reverse_0_get_values(unsigned int i,double& x, double& x_bar, double& w, double& w_bar);
+ void hess_reverse_1(unsigned int i);
+ void hess_reverse_1_init_x_bar(unsigned int);
+ void update_x_bar(unsigned int, double v);
+ void update_w_bar(unsigned int, double v);
+ void hess_reverse_1_get_xw(unsigned int, double&,double&);
+ void hess_reverse_get_x(unsigned int,double& x);
+ void hess_reverse_1_clear_index();
+
+ void nonlinearEdges(EdgeSet&);
+
+ string toString(int level);
+
+private:
+ UaryOPNode(OPCODE op, Node* left);
+ void calc_eval_function();
+ void calc_grad_reverse_0();
+ void hess_forward_calc0(unsigned int& len, double* lvec,double* ret_vec);
+};
+
+} /* namespace AutoDiff */
+#endif /* UARYOPNODE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/VNode.cpp b/src/boost/libs/yap/example/autodiff_library/VNode.cpp
new file mode 100644
index 00000000..285af01f
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/VNode.cpp
@@ -0,0 +1,149 @@
+/*
+ * VNode.cpp
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#include "VNode.h"
+#include "Tape.h"
+#include "Stack.h"
+
+using namespace std;
+
+namespace AutoDiff {
+
+#if FORWARD_ENABLED
+int VNode::DEFAULT_ID = -1;
+#endif
+
+VNode::VNode(double v) : ActNode(), val(v),u(NaN_Double)
+#if FORWARD_ENABLED
+,id(DEFAULT_ID)
+#endif
+{
+}
+
+VNode::~VNode() {
+}
+
+void VNode::collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total)
+{
+ total++;
+ boost::unordered_set<Node*>::iterator it = nodes.find(this);
+ if(it==nodes.end())
+ nodes.insert(this);
+}
+
+void VNode::inorder_visit(int level,ostream& oss)
+{
+ oss<<this->toString(level)<<endl;
+}
+
+void VNode::eval_function()
+{
+ SV->push_back(val);
+}
+
+string VNode::toString(int level)
+{
+ ostringstream oss;
+ string s(level,'\t');
+ oss<<s<<"[VNode](index:"<<index<<",val:"<<val<<",u:"<<u<<") - "<<this;
+ return oss.str();
+}
+
+void VNode::grad_reverse_0()
+{
+ this->adj = 0;
+ SV->push_back(val);
+}
+
+void VNode::grad_reverse_1()
+{
+ //do nothing
+ //this is a leaf node
+}
+
+#if FORWARD_ENABLED
+void VNode::hess_forward(unsigned int len, double** ret_vec)
+{
+ assert(id!=DEFAULT_ID);
+ (*ret_vec) = new double[len];
+ std::fill_n(*ret_vec,len,0);
+ (*ret_vec)[id]=1;
+ SV->push_back(this->val);
+}
+#endif
+
+unsigned int VNode::hess_reverse_0()
+{
+ if(index==0)
+ {//this node is not on tape
+ double nan = NaN_Double;
+ TT->set(val); //x_i
+ TT->set(nan); //x_bar_i
+ TT->set(u); //w_i
+ TT->set(nan); //w_bar_i
+ index = TT->index;
+ }
+// cout<<toString(0)<<" -- "<<index<<endl;
+ return index;
+}
+
+void VNode::hess_reverse_0_get_values(unsigned int i,double& x, double& x_bar, double& w, double& w_bar)
+{
+ w_bar = TT->get(--i);
+ w = TT->get(--i);
+ x_bar = TT->get(--i);
+ x = TT->get(--i);
+}
+
+void VNode::hess_reverse_1(unsigned int i)
+{
+ n_in_arcs--;
+ //leaf node do nothing
+}
+
+void VNode::hess_reverse_1_init_x_bar(unsigned int i)
+{
+ TT->at(i-3) = 1;
+}
+
+void VNode::update_x_bar(unsigned int i ,double v)
+{
+// cout<<toString(0)<<" --- "<<__FUNCTION__<<" v="<<TT->at(i-3)<<"+"<<v<<endl;
+ TT->at(i-3) = isnan(TT->get(i-3))? v: TT->get(i-3) + v;
+}
+
+void VNode::update_w_bar(unsigned int i,double v)
+{
+// cout<<toString(0)<<" --- "<<__FUNCTION__<<" v="<<TT->at(i-1)<<"+"<<v<<endl;
+ TT->at(i-1) = isnan(TT->get(i-1))? v: TT->get(i-1) + v;
+}
+void VNode::hess_reverse_1_get_xw(unsigned int i, double& w,double& x)
+{
+ //cout<<toString(0)<<" --- "<<__FUNCTION__<<" w="<<TT->get(i-2)<<"-- "<<"x="<<TT->get(i-4)<<endl;
+ w = TT->get(i-2);
+ x = TT->get(i-4);
+}
+void VNode::hess_reverse_get_x(unsigned int i ,double& x)
+{
+ x = TT->get(i-4);
+}
+
+void VNode::nonlinearEdges(EdgeSet& edges)
+{
+// for(list<Edge>::iterator it = edges.edges.begin();it!=edges.edges.end();)
+// {
+// Edge e=*it;
+//
+// }
+}
+
+
+TYPE VNode::getType()
+{
+ return VNode_Type;
+}
+}
diff --git a/src/boost/libs/yap/example/autodiff_library/VNode.h b/src/boost/libs/yap/example/autodiff_library/VNode.h
new file mode 100644
index 00000000..d9673d4b
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/VNode.h
@@ -0,0 +1,52 @@
+/*
+ * VNode.h
+ *
+ * Created on: 8 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef VNODE_H_
+#define VNODE_H_
+
+#include "ActNode.h"
+
+namespace AutoDiff {
+class VNode: public ActNode {
+public:
+ VNode(double v=NaN_Double);
+ virtual ~VNode();
+ void collect_vnodes(boost::unordered_set<Node*>& nodes,unsigned int& total);
+ void eval_function();
+ void grad_reverse_0();
+ void grad_reverse_1();
+ unsigned int hess_reverse_0();
+ void hess_reverse_0_get_values(unsigned int i,double& x, double& x_bar, double& w, double& w_bar);
+ void hess_reverse_1(unsigned int i);
+ void hess_reverse_1_init_x_bar(unsigned int);
+ void update_x_bar(unsigned int,double);
+ void update_w_bar(unsigned int,double);
+ void hess_reverse_1_get_xw(unsigned int,double&,double&);
+ void hess_reverse_get_x(unsigned int,double& x);
+
+ void nonlinearEdges(EdgeSet&);
+
+ void inorder_visit(int level,ostream& oss);
+ string toString(int level);
+ TYPE getType();
+
+#if FORWARD_ENABLED
+ void hess_forward(unsigned int nvar, double** ret_vec);
+ //! used for only forward hessian
+ //! the id has to be assigned starting from 0
+ int id;
+ static int DEFAULT_ID;
+#endif
+ double val;
+ double u;
+
+
+};
+
+} // end namespace foo
+
+#endif /* VNODE_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/auto_diff_types.h b/src/boost/libs/yap/example/autodiff_library/auto_diff_types.h
new file mode 100644
index 00000000..b24c59a1
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/auto_diff_types.h
@@ -0,0 +1,26 @@
+/*
+ * auto_diff_types.h
+ *
+ * Created on: 18 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef AUTO_DIFF_TYPES_H_
+#define AUTO_DIFF_TYPES_H_
+
+namespace AutoDiff{
+
+#define FORWARD_ENABLED 0
+#if FORWARD_ENABLED
+extern unsigned int num_var;
+#endif
+
+#define NaN_Double std::numeric_limits<double>::quiet_NaN()
+
+typedef enum { OPNode_Type=0, VNode_Type, PNode_Type} TYPE;
+
+
+typedef enum {OP_PLUS=0, OP_MINUS, OP_TIMES, OP_DIVID, OP_SIN, OP_COS, OP_SQRT, OP_POW, OP_NEG} OPCODE;
+
+}
+#endif /* AUTO_DIFF_TYPES_H_ */
diff --git a/src/boost/libs/yap/example/autodiff_library/autodiff.cpp b/src/boost/libs/yap/example/autodiff_library/autodiff.cpp
new file mode 100644
index 00000000..5fae3686
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/autodiff.cpp
@@ -0,0 +1,335 @@
+//============================================================================
+// Name : autodiff.cpp
+// Author :
+// Version :
+// Copyright : Your copyright notice
+// Description : Hello World in C++, Ansi-style
+//============================================================================
+
+#include <iostream>
+#include <sstream>
+#include <numeric>
+#include <boost/foreach.hpp>
+#include "autodiff.h"
+#include "Stack.h"
+#include "Tape.h"
+#include "BinaryOPNode.h"
+#include "UaryOPNode.h"
+
+using namespace std;
+
+namespace AutoDiff
+{
+
+#if FORWARD_ENABLED
+
+unsigned int num_var = 0;
+
+void hess_forward(Node* root, unsigned int nvar, double** hess_mat)
+{
+ assert(nvar == num_var);
+ unsigned int len = (nvar+3)*nvar/2;
+ root->hess_forward(len,hess_mat);
+}
+
+#endif
+
+
+PNode* create_param_node(double value){
+ return new PNode(value);
+}
+VNode* create_var_node(double v)
+{
+ return new VNode(v);
+}
+OPNode* create_binary_op_node(OPCODE code, Node* left, Node* right)
+{
+ return BinaryOPNode::createBinaryOpNode(code,left,right);
+}
+OPNode* create_uary_op_node(OPCODE code, Node* left)
+{
+ return UaryOPNode::createUnaryOpNode(code,left);
+}
+double eval_function(Node* root)
+{
+ assert(SD->size()==0);
+ assert(SV->size()==0);
+ root->eval_function();
+ assert(SV->size()==1);
+ double val = SV->pop_back();
+ return val;
+}
+
+double grad_reverse(Node* root,vector<Node*>& vnodes, vector<double>& grad)
+{
+ grad.clear();
+ BOOST_FOREACH(Node* node, vnodes)
+ {
+ assert(node->getType()==VNode_Type);
+ static_cast<VNode*>(node)->adj = NaN_Double;
+ }
+
+ assert(SD->size()==0);
+ root->grad_reverse_0();
+ assert(SV->size()==1);
+ root->grad_reverse_1_init_adj();
+ root->grad_reverse_1();
+ assert(SD->size()==0);
+ double val = SV->pop_back();
+ assert(SV->size()==0);
+ //int i=0;
+ BOOST_FOREACH(Node* node, vnodes)
+ {
+ assert(node->getType()==VNode_Type);
+ grad.push_back(static_cast<VNode*>(node)->adj);
+ static_cast<VNode*>(node)->adj = NaN_Double;
+ }
+ assert(grad.size()==vnodes.size());
+ //all nodes are VNode and adj == NaN_Double -- this reset adj for this expression tree by root
+ return val;
+}
+
+double grad_reverse(Node* root, vector<Node*>& vnodes, col_compress_matrix_row& rgrad)
+{
+ BOOST_FOREACH(Node* node, vnodes)
+ {
+ assert(node->getType()==VNode_Type);
+ static_cast<VNode*>(node)->adj = NaN_Double;
+ }
+ assert(SD->size()==0);
+ root->grad_reverse_0();
+ assert(SV->size()==1);
+ root->grad_reverse_1_init_adj();
+ root->grad_reverse_1();
+ assert(SD->size()==0);
+ double val = SV->pop_back();
+ assert(SV->size()==0);
+ unsigned int i =0;
+ BOOST_FOREACH(Node* node, vnodes)
+ {
+ assert((node)->getType()==VNode_Type);
+ double diff = static_cast<VNode*>(node)->adj;
+ if(!isnan(diff)){
+ rgrad(i) = diff;
+ static_cast<VNode*>(node)->adj = NaN_Double;
+ }
+ i++;
+ }
+ //all nodes are VNode and adj == NaN_Double -- this reset adj for this expression tree by root
+ assert(i==vnodes.size());
+ return val;
+}
+
+double hess_reverse(Node* root,vector<Node*>& vnodes,vector<double>& dhess)
+{
+ TT->clear();
+ II->clear();
+ assert(TT->empty());
+ assert(II->empty());
+ assert(TT->index==0);
+ assert(II->index==0);
+ dhess.clear();
+
+// for(vector<Node*>::iterator it=nodes.begin();it!=nodes.end();it++)
+// {
+// assert((*it)->getType()==VNode_Type);
+// (*it)->index = 0;
+// } //this work complete in hess-reverse_0_init_index
+
+ assert(root->n_in_arcs == 0);
+ root->hess_reverse_0_init_n_in_arcs();
+ assert(root->n_in_arcs == 1);
+ root->hess_reverse_0();
+ double val = NaN_Double;
+ root->hess_reverse_get_x(TT->index,val);
+// cout<<TT->toString();
+// cout<<endl;
+// cout<<II->toString();
+// cout<<"======================================= hess_reverse_0"<<endl;
+ root->hess_reverse_1_init_x_bar(TT->index);
+ assert(root->n_in_arcs == 1);
+ root->hess_reverse_1(TT->index);
+ assert(root->n_in_arcs == 0);
+ assert(II->index==0);
+// cout<<TT->toString();
+// cout<<endl;
+// cout<<II->toString();
+// cout<<"======================================= hess_reverse_1"<<endl;
+
+ for(vector<Node*>::iterator it=vnodes.begin();it!=vnodes.end();it++)
+ {
+ assert((*it)->getType()==VNode_Type);
+ dhess.push_back(TT->get((*it)->index-1));
+ }
+
+ TT->clear();
+ II->clear();
+ root->hess_reverse_1_clear_index();
+ return val;
+}
+
+double hess_reverse(Node* root,vector<Node*>& vnodes,col_compress_matrix_col& chess)
+{
+ TT->clear();
+ II->clear();
+ assert(TT->empty());
+ assert(II->empty());
+ assert(TT->index==0);
+ assert(II->index==0);
+
+// for(vector<Node*>::iterator it=nodes.begin();it!=nodes.end();it++)
+// {
+// assert((*it)->getType()==VNode_Type);
+// (*it)->index = 0;
+// } //this work complete in hess-reverse_0_init_index
+
+ assert(root->n_in_arcs == 0);
+ //reset node index and n_in_arcs - for the Tape location
+ root->hess_reverse_0_init_n_in_arcs();
+ assert(root->n_in_arcs == 1);
+ root->hess_reverse_0();
+ double val = NaN_Double;
+ root->hess_reverse_get_x(TT->index,val);
+// cout<<TT->toString();
+// cout<<endl;
+// cout<<II->toString();
+// cout<<"======================================= hess_reverse_0"<<endl;
+ root->hess_reverse_1_init_x_bar(TT->index);
+ assert(root->n_in_arcs == 1);
+ root->hess_reverse_1(TT->index);
+ assert(root->n_in_arcs == 0);
+ assert(II->index==0);
+// cout<<TT->toString();
+// cout<<endl;
+// cout<<II->toString();
+// cout<<"======================================= hess_reverse_1"<<endl;
+
+ unsigned int i =0;
+ BOOST_FOREACH(Node* node, vnodes)
+ {
+ assert(node->getType() == VNode_Type);
+ //node->index = 0 means this VNode is not in the tree
+ if(node->index!=0)
+ {
+ double hess = TT->get(node->index -1);
+ if(!isnan(hess))
+ {
+ chess(i) = chess(i) + hess;
+ }
+ }
+ i++;
+ }
+ assert(i==vnodes.size());
+ root->hess_reverse_1_clear_index();
+ TT->clear();
+ II->clear();
+ return val;
+}
+
+unsigned int nzGrad(Node* root)
+{
+ unsigned int nzgrad,total = 0;
+ boost::unordered_set<Node*> nodes;
+ root->collect_vnodes(nodes,total);
+ nzgrad = nodes.size();
+ return nzgrad;
+}
+
+/*
+ * number of non-zero gradient in constraint tree root that also belong to vSet
+ */
+unsigned int nzGrad(Node* root, boost::unordered_set<Node*>& vSet)
+{
+ unsigned int nzgrad=0, total=0;
+ boost::unordered_set<Node*> vnodes;
+ root->collect_vnodes(vnodes,total);
+ //cout<<"nzGrad - vnodes size["<<vnodes.size()<<"] -- total node["<<total<<"]"<<endl;
+ for(boost::unordered_set<Node*>::iterator it=vnodes.begin();it!=vnodes.end();it++)
+ {
+ Node* n = *it;
+ if(vSet.find(n) != vSet.end())
+ {
+ nzgrad++;
+ }
+ }
+ return nzgrad;
+}
+
+void nonlinearEdges(Node* root, EdgeSet& edges)
+{
+ root->nonlinearEdges(edges);
+}
+
+unsigned int nzHess(EdgeSet& eSet,boost::unordered_set<Node*>& set1, boost::unordered_set<Node*>& set2)
+{
+ list<Edge>::iterator i = eSet.edges.begin();
+ for(;i!=eSet.edges.end();)
+ {
+ Edge e =*i;
+ Node* a = e.a;
+ Node* b = e.b;
+ if((set1.find(a)!=set1.end() && set2.find(b)!=set2.end())
+ ||
+ (set1.find(b)!=set1.end() && set2.find(a)!=set2.end()))
+ {
+ //e is connected between set1 and set2
+ i++;
+ }
+ else
+ {
+ i = eSet.edges.erase(i);
+ }
+ }
+ unsigned int diag=eSet.numSelfEdges();
+ unsigned int nzHess = (eSet.size())*2 - diag;
+ return nzHess;
+}
+
+unsigned int nzHess(EdgeSet& edges)
+{
+ unsigned int diag=edges.numSelfEdges();
+ unsigned int nzHess = (edges.size())*2 - diag;
+ return nzHess;
+}
+
+unsigned int numTotalNodes(Node* root)
+{
+ unsigned int total = 0;
+ boost::unordered_set<Node*> nodes;
+ root->collect_vnodes(nodes,total);
+ return total;
+}
+
+string tree_expr(Node* root)
+{
+ ostringstream oss;
+ oss<<"visiting tree == "<<endl;
+ int level = 0;
+ root->inorder_visit(level,oss);
+ return oss.str();
+}
+
+void print_tree(Node* root)
+{
+ cout<<"visiting tree == "<<endl;
+ int level = 0;
+ root->inorder_visit(level,cout);
+}
+
+void autodiff_setup()
+{
+ Stack::diff = new Stack();
+ Stack::vals = new Stack();
+ Tape<unsigned int>::indexTape = new Tape<unsigned int>();
+ Tape<double>::valueTape = new Tape<double>();
+}
+
+void autodiff_cleanup()
+{
+ delete Stack::diff;
+ delete Stack::vals;
+ delete Tape<unsigned int>::indexTape;
+ delete Tape<double>::valueTape;
+}
+
+} //AutoDiff namespace end
diff --git a/src/boost/libs/yap/example/autodiff_library/autodiff.h b/src/boost/libs/yap/example/autodiff_library/autodiff.h
new file mode 100644
index 00000000..738cb3f9
--- /dev/null
+++ b/src/boost/libs/yap/example/autodiff_library/autodiff.h
@@ -0,0 +1,114 @@
+/*
+ * autodiff.h
+ *
+ * Created on: 16 Apr 2013
+ * Author: s0965328
+ */
+
+#ifndef AUTODIFF_H_
+#define AUTODIFF_H_
+#include <boost/unordered_set.hpp>
+#include <boost/numeric/ublas/matrix_proxy.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/matrix_sparse.hpp>
+#include <boost/numeric/ublas/io.hpp>
+#include "auto_diff_types.h"
+#include "Node.h"
+#include "VNode.h"
+#include "OPNode.h"
+#include "PNode.h"
+#include "ActNode.h"
+#include "EdgeSet.h"
+
+
+/*
+ * + Function and Gradient Evaluation
+ * The tapeless implementation for function and derivative evaluation
+ * Advantage for tapeless:
+ * Low memory usage
+ * Function evaluation use one stack
+ * Gradient evaluation use two stack.
+ * Disadvantage for tapeless:
+ * Inefficient if the expression tree have repeated nodes.
+ * for example:
+ * root
+ * / \
+ * * *
+ * / \ / \
+ * x1 x1 x1 x1
+ * Tapeless implementation will go through all the edges.
+ * ie. adjoint of x will be updated 4 times for the correct
+ * gradient of x1.While the tape implemenation can discovery this
+ * dependence and update adjoint of x1 just twice. The computational
+ * graph (DAG) for a taped implemenation will be look like bellow.
+ * root
+ * /\
+ * *
+ * /\
+ * x1
+ *
+ * + Forward Hessian Evaluation:
+ * This is an inefficient implementation of the forward Hessian method. It will evaluate the diagonal
+ * and upper triangular of the Hessian. The gradient is also evaluation in the same routine. The result
+ * will be returned in an array.
+ * To use this method, one have to provide a len parameter. len = (nvar+3)*nvar/2 where nvar is the number
+ * of independent variables. ie. x_1 x_2 ... x_nvar. And the varaible id need to be a consequent integer start
+ * with 0.
+ * ret_vec will contains len number of doubles. Where the first nvar elements is the gradient vector,
+ * and the rest of (nvar+1)*nvar/2 elements are the upper/lower plus the diagonal part of the Hessian matrix
+ * in row format.
+ * This algorithm is inefficient, because at each nodes, it didn't check the dependency of the independent
+ * variables up to the current node. (or it is hard to do so for this setup). Therefore, it computes a full
+ * for loops over each independent variable (ie. assume they are all dependent), for those independent
+ * variables that are not dependent at the current node, zero will be produced by computation.
+ * By default the forward mode hessian routing is disabled. To enable the forward hessian interface, the
+ * compiler marco FORWARD_ENABLED need to be set equal to 1 in auto_diff_types.h
+ *
+ * + Reverse Hessian*Vector Evaluation:
+ * Simple, building a tape in the forward pass, and a reverse pass will evaluate the Hessian*vector. The implemenation
+ * also discovery the repeated subexpression and use one piece of memory on the tape for the same subexpression. This
+ * allow efficient evaluation, because the repeated subexpression only evaluate once in the forward and reverse pass.
+ * This algorithm can be called n times to compute a full Hessian, where n equals the number of independent
+ * variables.
+ * */
+
+typedef boost::numeric::ublas::compressed_matrix<double,boost::numeric::ublas::column_major,0,std::vector<std::size_t>,std::vector<double> > col_compress_matrix;
+typedef boost::numeric::ublas::matrix_row<col_compress_matrix > col_compress_matrix_row;
+typedef boost::numeric::ublas::matrix_column<col_compress_matrix > col_compress_matrix_col;
+
+namespace AutoDiff{
+
+ //node creation methods
+ extern PNode* create_param_node(double value);
+ extern VNode* create_var_node(double v=NaN_Double);
+ extern OPNode* create_uary_op_node(OPCODE code, Node* left);
+ extern OPNode* create_binary_op_node(OPCODE code, Node* left,Node* right);
+
+ //single constraint version
+ extern double eval_function(Node* root);
+ extern unsigned int nzGrad(Node* root);
+ extern double grad_reverse(Node* root,vector<Node*>& nodes, vector<double>& grad);
+ extern unsigned int nzHess(EdgeSet&);
+ extern double hess_reverse(Node* root, vector<Node*>& nodes, vector<double>& dhess);
+
+ //multiple constraints version
+ extern unsigned int nzGrad(Node* root, boost::unordered_set<Node*>& vnodes);
+ extern double grad_reverse(Node* root, vector<Node*>& nodes, col_compress_matrix_row& rgrad);
+ extern unsigned int nzHess(EdgeSet&,boost::unordered_set<Node*>& set1, boost::unordered_set<Node*>& set2);
+ extern double hess_reverse(Node* root, vector<Node*>& nodes, col_compress_matrix_col& chess);
+
+#if FORWARD_ENDABLED
+ //forward methods
+ extern void hess_forward(Node* root, unsigned int nvar, double** hess_mat);
+#endif
+
+ //utiliy methods
+ extern void nonlinearEdges(Node* root, EdgeSet& edges);
+ extern unsigned int numTotalNodes(Node*);
+ extern string tree_expr(Node* root);
+ extern void print_tree(Node* root);
+ extern void autodiff_setup();
+ extern void autodiff_cleanup();
+};
+
+#endif /* AUTODIFF_H_ */