ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ChiSquareGradHessian.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ChiSquareGradHessian.cpp
1 #include "ChiSquareGradHessian.h"
2 
3 #include "Pincushion.h"
4 
5 #include <Eigen/LU>
6 
7 #include <memory>
8 
9 using namespace std;
10 using namespace Eigen;
11 using namespace SeamStress;
12 
13 namespace FitNewton
14 {
15  ChiSquareGradHessian::ChiSquareGradHessian(FunctionGradHessian* func_instance, unsigned long int numthreads) : FunctionGradHessian(func_instance->nPars(), 0), func(func_instance), data_has_errors(false), errors_are_weights(false)
16  {
17  Seamstress::init_vector(numthreads, vss);
18 
19  vssp = new vector<Seamstress*>();
20  for(unsigned long int i=0;i<vss.size();i++){vssp->push_back(&(vss[i]));}
21 
23 
24  nthreads = numthreads;
25 
26  pthread_mutexattr_init(&mattr);
27  pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL);
28  pthread_mutex_init(&mutex, &mattr);
29  }
30 
31 
33  {
34  for(unsigned int i=0;i<nthreads;i++)
35  {
36  vss[i].stop();
37  }
38  delete pins;
39  delete vssp;
40  }
41 
42 
44  {
46  clone->setData(*data);
47  clone->setPoints(*points);
48  if(data_has_errors==true){clone->setErrors(*data_errors);}
49  return clone;
50  }
51 
52 
53  void ChiSquareGradHessian::computeCovariance(const double& val, const MatrixXd& hessian)
54  {
55  covariance = hessian.inverse();
56 // hessian.computeInverse(&covariance);
57  if(data_has_errors==false){covariance *= (val/( (double)(points->size() - npars) ) );}
58  else if(errors_are_weights==true)
59  {
60  double scale = 0.;
61  for(unsigned int i=0;i<data_errors->size();i++)
62  {
63  double temp = 1./((*data_errors)[i]);temp*=temp;
64  scale += temp;
65  }
66  covariance *= val/(scale - (double)npars);
67  }
68  }
69 
70 
72  {
73  cov = covariance;
74  }
75 
76 
77  bool ChiSquareGradHessian::calcValGradHessian(const VectorXd& x, double& val, VectorXd& grad, MatrixXd& hessian)
78  {
79  current_eval = &x;
80  bool bounds = true;
81  FunctionGradHessian* func_instance = func->Clone();
82  for(unsigned int j=0;j<(*points)[0].size();j++){func_instance->setFixedPar(j, (*points)[0][j]);}
83  bounds = func_instance->calcValGrad((*current_eval), val, grad);
84  delete func_instance;
85 
86 
87  val=0.;
88  grad = VectorXd::Zero(npars);
89  hessian = MatrixXd::Zero(npars, npars);
90 
91  val_output = &val;
92  grad_output = &grad;
93  hessian_output = &hessian;
94 
95  covariance = MatrixXd::Zero(npars, npars);
96 
97  niter = points->size();
99  else{thread_tot=nthreads;}
101  return bounds;
102  }
103 
104 
106  {
107  unsigned long int w = (*((unsigned long int *)arg));
108  unsigned long int part = niter/thread_tot;
109  unsigned long int rem = niter - part*thread_tot;
110  unsigned long int start = 0;
111  unsigned long int end = 0;
112  if(w<rem)
113  {
114  start = (part+1)*w;
115  end = start + part;
116  }
117  else
118  {
119  start = (part+1)*rem;
120  start += (part*(w-rem));
121  end = start + part - 1;
122  }
123 
124  //initialize the val, grad, and hessian to be added to those of the main thread
125  double temp_val=0.;
126  VectorXd temp_grad = VectorXd::Zero(npars);
127  MatrixXd temp_hessian = MatrixXd::Zero(npars, npars);
128 
129  //initialize the val, grad, and hessian of the function with fixed parameters at the given points vector
130  double temp_val2=0.;
131  VectorXd temp_grad2 = VectorXd::Zero(npars);
132  MatrixXd temp_hessian2 = MatrixXd::Zero(npars, npars);
133 
134  VectorXd cur_grad = VectorXd::Zero(npars);
135 
136  //f += (t - v)^2
137  //df/dx += 2*[ t - v ]*(dt/dx)
138  //d^2f/dxdy += 2*[(dt/dy)*(dt/dx) + [t-v]*(d^2t/dxdy) ]
139 
140  FunctionGradHessian* func_instance = func->Clone();
141 
142  for(unsigned long int i=(start);i<=(end);i++)
143  {
144  for(unsigned int j=0;j<(*points)[i].size();j++){func_instance->setFixedPar(j, (*points)[i][j]);}
145  func_instance->calcValGradHessian((*current_eval), temp_val2, temp_grad2, temp_hessian2);
146  double inv_variance = 1.;
147  if(data_has_errors==true){inv_variance = 1./(*data_errors)[i];inv_variance*=inv_variance;}
148 
149  double temp1 = (temp_val2 - (*data)[i]);
150  temp_val += temp1*temp1*inv_variance;
151 
152  for(unsigned int j=0;j<npars;j++)
153  {
154  cur_grad(j) = 2.*temp1*temp_grad2(j)*inv_variance;
155  temp_grad(j) += cur_grad(j);
156  }
157 
158  for(unsigned int k=0;k<npars;k++)
159  {
160  for(unsigned int j=0;j<npars;j++)
161  {
162  temp_hessian(j,k) += 2.*inv_variance*(temp_grad2(j)*temp_grad2(k) + temp1*temp_hessian2(j,k));
163  }
164  }
165  }
166 
167 
168  pthread_mutex_lock(&mutex);
169  (*val_output) += temp_val;
170  (*grad_output) += temp_grad;
171  (*hessian_output) += temp_hessian;
172  pthread_mutex_unlock(&mutex);
173 
174 
175 
176  delete func_instance;
177  }
178 
179 
180  bool ChiSquareGradHessian::calcValGrad(const VectorXd& x, double& val, VectorXd& grad)
181  {
182  current_eval = &x;
183  bool bounds = true;
184  FunctionGradHessian* func_instance = func->Clone();
185  for(unsigned int j=0;j<(*points)[0].size();j++){func_instance->setFixedPar(j, (*points)[0][j]);}
186  bounds = func_instance->calcValGrad((*current_eval), val, grad);
187  delete func_instance;
188 
189  val=0.;
190  grad = VectorXd::Zero(npars);
191 
192  val_output = &val;
193  grad_output = &grad;
194 
195  niter = points->size();
197  else{thread_tot=nthreads;}
199  return bounds;
200  }
201 
202 
204  {
205  unsigned long int w = (*((unsigned long int *)arg));
206  unsigned long int part = niter/thread_tot;
207  unsigned long int rem = niter - part*thread_tot;
208  unsigned long int start = 0;
209  unsigned long int end = 0;
210  if(w<rem)
211  {
212  start = (part+1)*w;
213  end = start + part;
214  }
215  else
216  {
217  start = (part+1)*rem;
218  start += (part*(w-rem));
219  end = start + part - 1;
220  }
221 
222  //initialize the val, grad, and hessian to be added to those of the main thread
223  double temp_val=0.;
224  VectorXd temp_grad = VectorXd::Zero(npars);
225 
226  //initialize the val, grad, and hessian of the function with fixed parameters at the given points vector
227  double temp_val2=0.;
228  VectorXd temp_grad2 = VectorXd::Zero(npars);
229 
230  VectorXd cur_grad = VectorXd::Zero(npars);
231 
232  //f += (t - v)^2
233  //df/dx += 2*[ t - v ]*(dt/dx)
234  //d^2f/dxdy += 2*[(dt/dy)*(dt/dx) + [t-v]*(d^2t/dxdy) ]
235 
236  FunctionGradHessian* func_instance = func->Clone();
237 
238  for(unsigned long int i=(start);i<=(end);i++)
239  {
240  for(unsigned int j=0;j<(*points)[i].size();j++){func_instance->setFixedPar(j, (*points)[i][j]);}
241  func_instance->calcValGrad((*current_eval), temp_val2, temp_grad2);
242  double inv_variance = 1.;
243  if(data_has_errors==true){inv_variance = 1./(*data_errors)[i];inv_variance*=inv_variance;}
244 
245  double temp1 = (temp_val2 - (*data)[i]);
246  temp_val += temp1*temp1*inv_variance;
247 
248  for(unsigned int j=0;j<npars;j++)
249  {
250  cur_grad(j) = 2.*temp1*temp_grad2(j)*inv_variance;
251  temp_grad(j) += cur_grad(j);
252  }
253  }
254 
255 
256  pthread_mutex_lock(&mutex);
257  (*val_output) += temp_val;
258  (*grad_output) += temp_grad;
259  pthread_mutex_unlock(&mutex);
260 
261 
262 
263  delete func_instance;
264  }
265 
266 }
267 
268