21 fDim = Get<int>(
fitMan->
raw()[
"General"][
"PSO"][
"TestLikelihoodDim"], __FILE__, __LINE__);
35 if (syst->GetDoAdaption()) {
36 MACH3LOG_ERROR(
"Param Handler {} has enabled Adaption, this is not needed for {} so please turn it off", syst->GetName(),
GetName());
43 for(
int i = 0; i <
fDim; ++i){
45 outTree->Branch(Form(
"Parameter_%d", i),
paramlist[i].data(), Form(
"Parameter_%d[nParts]/D",i));
69 for (
int i = 0; i <
fDim; i++){
77 for (std::vector<ParameterHandlerBase*>::iterator it =
systematics.begin(); it !=
systematics.end(); ++it){
80 fDim += (*it)->GetNumParams();
81 for(
int i = 0; i < (*it)->GetNumParams(); ++i)
83 double curr = (*it)->GetParPreFit(i);
84 double lim = 10.0*(*it)->GetDiagonalError(i);
85 double low = (*it)->GetLowerBound(i);
86 double high = (*it)->GetUpperBound(i);
87 if(low > curr - lim)
ranges_min.push_back(low);
89 if(high < curr + lim)
ranges_min.push_back(high);
91 prior.push_back(curr);
93 if((*it)->IsParameterFixed(i)){
103 fDim += (*it)->GetNParameters();
104 for(
int i = 0; i < (*it)->GetNParameters(); ++i)
108 prior.push_back((*it)->GetParPreFit(i));
109 if((*it)->GetPCAHandler()->IsParameterFixedPCA(i)){
120 MACH3LOG_INFO(
"Printing Minimums and Maximums of Variables to be minimized");
121 for (
int i = 0; i <
fDim; i++){
127 std::vector<double> init_position;
128 std::vector<double> init_velocity;
131 for (
int j=0; j<
fDim; ++j){
133 init_position.push_back(
prior[j]);
134 init_velocity.push_back(0.0);
141 init_velocity.push_back((2.0*
random->Rndm()-1.0));
144 system.emplace_back(std::make_unique<particle>(init_position, init_velocity));
145 auto& new_particle =
system.back();
146 new_particle->set_personal_best_position(init_position);
147 double new_value =
CalcChi(init_position);
148 new_particle->set_personal_best_value(new_value);
149 new_particle->set_value(new_value);
158 std::vector<std::vector<double> >
PSO::bisection(
const std::vector<double>& position,
const double minimum,
159 const double range,
const double precision) {
161 std::vector<std::vector<double>> uncertainties_list;
162 for (
unsigned int i = 0; i< position.size(); ++i) {
165 std::vector<double> new_position = position; new_position[i] = position[i]-range;
166 double val_1 =
CalcChi(new_position)-minimum-1.0;
167 while (val_1*-1.0 > 0.0){
168 new_position[i] -= range;
169 val_1 =
CalcChi(new_position)-minimum-1.0;
171 std::vector<double> bisect_position = position; bisect_position[i] = bisect_position[i] - (position[i]-new_position[i])/2;
172 std::vector<std::vector<double>> position_list{new_position,bisect_position,position};
173 double val_2 =
CalcChi(bisect_position)-minimum-1.0;
174 std::vector<double> value_list{val_1,val_2, -1.0};
176 while (res > precision){
177 if (value_list[0] * value_list[1] < 0){
178 std::vector<double> new_bisect_position = position_list[0];
179 new_bisect_position[i] =new_bisect_position[i]+ (position_list[1][i]-position_list[0][i])/2;
180 double new_val =
CalcChi(new_bisect_position)-minimum-1.0;
181 position_list[2] = position_list[1];
182 value_list[2] = value_list[1];
183 value_list[1] = new_val;
184 position_list[1] = new_bisect_position;
185 res = std::abs(position[2]-position[0]);
188 std::vector<double> new_bisect_position = position_list[1];
189 new_bisect_position[i] += (position_list[2][i]-position_list[1][i])/2;
190 double new_val =
CalcChi(new_bisect_position)-minimum-1.0;
191 position_list[0] = position_list[1];
192 value_list[0] = value_list[1];
193 value_list[1] = new_val;
194 position_list[1] = new_bisect_position;
195 res = std::abs(position_list[2][i]-position_list[1][i]);
199 std::vector<double> new_position_p = position; new_position_p[i] = position[i]+range;
200 double val_1_p =
CalcChi(new_position_p)-minimum-1.0;
201 while (val_1_p * -1.0 > 0.0){
202 new_position_p[i] += range;
203 val_1_p =
CalcChi(new_position_p)-minimum-1.0;
205 std::vector<double> bisect_position_p = position; bisect_position_p[i] = bisect_position_p[i] += (new_position_p[i]-position[i])/2;
206 std::vector<std::vector<double>> position_list_p{position,bisect_position_p,new_position_p};
207 double val_2_p =
CalcChi(bisect_position_p)-minimum-1.0;
208 std::vector<double> value_list_p{-1.0,val_2_p, val_1_p};
210 while (res_p > precision){
211 if (value_list_p[0] * value_list_p[1] < 0){
212 std::vector<double> new_bisect_position_p = position_list_p[0];new_bisect_position_p[i] += (position_list_p[1][i]-position_list_p[0][i])/2;
213 double new_val_p =
CalcChi(new_bisect_position_p)-minimum-1.0;
214 position_list_p[2] = position_list_p[1];
215 value_list_p[2] = value_list_p[1];
216 value_list_p[1] = new_val_p;
217 position_list_p[1] = new_bisect_position_p;
218 res = std::abs(position[2]-position[0]);
219 res_p = std::abs(position_list_p[1][i]-position_list_p[0][i]);
223 std::vector<double> new_bisect_position_p = position_list_p[1];new_bisect_position_p[i] += (position_list_p[2][i]-position_list_p[1][i])/2;
224 double new_val_p =
CalcChi(new_bisect_position_p)-minimum-1.0;
225 position_list_p[0] = position_list_p[1];
226 value_list_p[0] = value_list_p[1];
227 value_list_p[1] = new_val_p;
228 position_list_p[1] = new_bisect_position_p;
229 res_p = std::abs(position_list_p[2][i]-position_list_p[1][i]);
233 uncertainties_list.push_back({std::abs(position[i]-position_list[1][i]),std::abs(position[i]-position_list_p[1][i])});
235 MACH3LOG_INFO(
"LLR values for ± positive and negative uncertainties are {:<10.2f} and {:<10.2f}",
238 return uncertainties_list;
244 std::vector<double> pos_uncertainty(position.size());
245 std::vector<double> neg_uncertainty(position.size());
246 constexpr
int num = 200;
247 std::vector<double> pos = position;
248 for (
unsigned int i = 0; i < position.size(); ++i) {
249 double curr_ival = pos[i];
251 double neg_stop = position[i] - 5e-2;
252 double pos_stop = position[i] + 5e-2;
253 double start = position[i];
254 std::vector<double> x(num);
255 std::vector<double> y(num);
256 double StepPoint = (start-neg_stop) / (num - 1);
257 double value = start;
258 for (
int j = 0; j < num; ++j) {
260 double LLR =
CalcChi(position) - minimum - 1.0;
267 int closest_index = 0;
268 double closest_value = std::abs(y[0]);
269 for (
unsigned int ii = 1; ii < y.size(); ++ii) {
270 double abs_y = std::abs(y[ii]);
271 if (abs_y < closest_value) {
273 closest_value = abs_y;
276 neg_uncertainty[i] = x[closest_index];
280 StepPoint = (pos_stop-start) / (num - 1);
282 for (
int j = 0; j < num; ++j) {
284 double LLR =
CalcChi(position) - minimum - 1.0;
291 closest_value = std::abs(y[0]);
292 for (
unsigned int ii = 1; ii < y.size(); ++ii) {
293 double abs_y = std::abs(y[ii]);
294 if (abs_y < closest_value) {
296 closest_value = abs_y;
299 pos_uncertainty[i] = x[closest_index];
301 std::vector<std::vector<double>> res{neg_uncertainty,pos_uncertainty};
308 std::vector<std::vector<double >> x_list;
309 std::vector<std::vector<double >> y_list;
310 std::vector<double> position = previous_pos;
311 constexpr
int num = 5000;
312 for (
unsigned int i = 0;i<previous_pos.size();++i){
313 double curr_ival = position[i];
314 double start = previous_pos[i] - 1e-1;
315 double stop = previous_pos[i] + 1e-1;
316 std::vector<double> x(num);
317 std::vector<double> y(num);
318 double StepPoint = (stop - start) / (num - 1);
319 double value = start;
321 for (
int j = 0;j < num; ++j) {
323 double LLR =
CalcChi(position);
328 position[i] = curr_ival;
331 for (
unsigned int k = 0; k < x.size(); ++k){
336 for (
unsigned int k = 0; k < x.size(); ++k){
346 std::vector<double> total_pos(
fDim,0.0);
353 std::vector<double> new_pos =
vector_add(
system[i]->get_position(), new_velocity);
354 transform(total_pos.begin(), total_pos.end(), new_pos.begin(), total_pos.begin(),[](
double x,
double y) {return x+y;});
356 for (
int j = 0; j <
fDim; ++j) {
365 if(
fixed[j]) new_pos[j] =
system[i]->get_position()[j];
370 for (
int j = 0; j <
fDim; ++j) {
372 velo += new_velocity[j]*new_velocity[j];
377 system[i]->set_velocity(new_velocity);
378 system[i]->set_position(new_pos);
379 double new_value =
CalcChi(new_pos);
380 if(new_value <=
system[i]->get_personal_best_value()) {
381 system[i]->set_personal_best_value(new_value);
382 system[i]->set_personal_best_position(new_pos);
391 std::vector<double> result(best_pos.size(), 0.0);
392 transform(total_pos.begin(), total_pos.end(), total_pos.begin(), [
this](
double val){return val/fParticles;});
393 transform(total_pos.begin(),total_pos.end(),best_pos.begin(),result.begin(),[](
double x,
double y) {return x-y;});
395 double mean_dist_sq = 0;
396 for (
int i = 0; i<
fDim; i++){
397 mean_dist_sq += result[i]*result[i];
406 double mean_dist_sq = 0;
428 for (
int j = 0; j <
fDim; ++j){
443 for (
int i = 0; i<
fDim; ++i){
453 TVectorD* PSOParValue =
new TVectorD(
fDim);
454 TVectorD* PSOParError =
new TVectorD(
fDim);
456 for(
int i = 0; i <
fDim; ++i)
458 (*PSOParValue)(i) = 0;
459 (*PSOParError)(i) = 0;
467 for(
int i = 0; i <
fDim; ++i){
468 (*PSOParValue)(i) = minimum[i];
475 if(!ParHandler->IsPCA())
477 for(
int i = 0; i < ParHandler->GetNumParams(); ++i, ++ParCounter)
479 double ParVal = minimum[ParCounter];
481 (*PSOParValue)(ParCounter) = ParVal;
484 if(ParHandler->IsParameterFixed(i))
486 (*PSOParError)(ParCounter) = ParHandler->GetDiagonalError(i);
493 TVectorD ParVals(ParHandler->GetNumParams());
494 TVectorD ParVals_PCA(ParHandler->GetNParameters());
496 TVectorD ErrorVals(ParHandler->GetNumParams());
497 TVectorD ErrorVals_PCA(ParHandler->GetNParameters());
501 const int StartVal = ParCounter;
502 for(
int i = 0; i < ParHandler->GetNParameters(); ++i, ++ParCounter)
504 ParVals_PCA(i) = minimum[ParCounter];
507 ParVals = (ParHandler->GetPCAHandler()->GetTransferMatrix())*ParVals_PCA;
508 ErrorVals = (ParHandler->GetPCAHandler()->GetTransferMatrix())*ErrorVals_PCA;
510 ParCounter = StartVal;
512 for(
int i = 0; i < ParHandler->GetNumParams(); ++i, ++ParCounter)
514 (*PSOParValue)(ParCounter) = ParVals(i);
515 (*PSOParError)(ParCounter) = std::fabs(ErrorVals(i));
518 if(ParHandler->GetPCAHandler()->IsParameterFixedPCA(i))
520 (*PSOParError)(ParCounter) = ParHandler->GetDiagonalError(i);
527 PSOParValue->Write(
"PSOParValue");
528 PSOParError->Write(
"PSOParError");
551 constexpr
double A = 10.0;
553 for (
int i = 0; i <
fDim; ++i) {
554 sum += x[i] * x[i] - A * cos(2.0 * 3.14 * x[i]);
556 double llh = A *
fDim + sum;
std::string GetName() const
Get name of class.
std::unique_ptr< TRandom3 > random
Random number.
int accCount
counts accepted steps
void SaveOutput()
Save output and close files.
TFile * outputFile
Output.
unsigned int step
current state
double accProb
current acceptance prob
std::string AlgorithmName
Name of fitting algorithm that is being used.
double stepTime
Time of single step.
Manager * fitMan
The manager for configuration handling.
std::unique_ptr< TStopwatch > stepClock
tells how long single step/fit iteration took
double logLCurr
current likelihood
int auto_save
auto save every N steps
bool fTestLikelihood
Necessary for some fitting algorithms like PSO.
TTree * outTree
Output tree with posteriors.
void SanitiseInputs()
Remove obsolete memory and make other checks before fit starts.
std::vector< ParameterHandlerBase * > systematics
Systematic holder.
Implementation of base Likelihood Fit class, it is mostly responsible for likelihood calculation whil...
void PrepareFit()
prepare output and perform sanity checks
virtual double CalcChi2(const double *x)
Chi2 calculation over all included samples and syst objects.
Custom exception class used throughout MaCh3.
The manager class is responsible for managing configurations and settings.
YAML::Node const & raw() const
Return config.
std::vector< std::unique_ptr< particle > > system
std::vector< double > ranges_max
std::vector< double > vector_subtract(const std::vector< double > &v1, const std::vector< double > &v2)
std::vector< std::vector< double > > bisection(const std::vector< double > &position, const double minimum, const double range, const double precision)
std::vector< std::vector< double > > paramlist
std::vector< double > vector_multiply(std::vector< double > velocity, const double mul)
particle * get_best_particle()
std::vector< bool > fixed
std::vector< std::vector< double > > calc_uncertainty(const std::vector< double > &position, const double minimum)
std::vector< double > three_vector_addition(std::vector< double > vec1, const std::vector< double > &vec2, const std::vector< double > &vec3)
void set_best_particle(particle *n)
double vel[kMaxParticles]
PSO(Manager *const fitMan)
constructor
double CalcChi(std::vector< double > x)
std::vector< double > vector_add(const std::vector< double > &v1, const std::vector< double > &v2)
std::vector< std::vector< double > > uncertainties
std::vector< double > ranges_min
void RunMCMC() final
Actual implementation of PSO Fit algorithm.
double CalcChi2(const double *x) final
Chi2 calculation over all included samples and syst objects.
double rastriginFunc(const double *x)
Evaluates the Rastrigin function for a given parameter values.
std::vector< double > prior
void uncertainty_check(const std::vector< double > &previous_pos)
std::vector< double > get_personal_best_position()
constexpr static const double _LARGE_LOGL_
Large Likelihood is used it parameter go out of physical boundary, this indicates in MCMC that such s...