CMS 3D CMS Logo

VoronoiAlgorithm.cc
Go to the documentation of this file.
1 #include "VoronoiAlgorithm.h"
2 
3 #include <cmath>
4 namespace {
5 inline
6 double normalizedPhi(double phi) {
7  static double const TWO_PI = M_PI * 2;
8  while ( phi < -M_PI ) phi += TWO_PI;
9  while ( phi > M_PI ) phi -= TWO_PI;
10  return phi;
11 }
12 
13 
14 }
15 
16 extern "C" {
17 
18  extern struct ascal_s {
19  double objnor;
20  double rhsnor;
21  double scdiff;
22  int scpass;
23  int scalmet;
24  } ascal_;
25 
26  extern struct compl_s {
27  double climit;
28  double ccorr;
29  } compl_;
30 
31  extern struct dims_s {
32  int n;
33  int n1;
34  int m;
35  int mn;
36  int nz;
37  int cfree;
38  int pivotn;
39  int denwin;
40  int rfree;
41  } dims_;
42 
43  extern struct drop_s {
44  double tfixvar;
45  double tfixslack;
46  double slklim;
47  } drop_;
48 
49  extern struct factor_s {
50  double tpiv1;
51  double tpiv2;
52  double tabs;
53  double trabs;
54  double lam;
55  double tfind;
56  double order;
57  double supdens;
58  } factor_;
59 
60  extern struct initv_s {
61  double prmin;
62  double upmax;
63  double dumin;
64  int stamet;
65  int safmet;
66  int premet;
67  int regul;
68  } initv_;
69 
70  extern struct itref_s {
71  double tresx;
72  double tresy;
73  int maxref;
74  } itref_;
75 
76  extern struct mscal_s {
77  double varadd;
78  double slkadd;
79  double scfree;
80  } mscal_;
81 
82  extern struct numer_s {
83  double tplus;
84  double tzer;
85  } numer_;
86 
87  extern struct param_s {
88  double palpha;
89  double dalpha;
90  } param_;
91 
92  extern struct predc_s {
93  double target;
94  double tsmall;
95  double tlarge;
96  double center;
97  double corstp;
98  int mincc;
99  int maxcc;
100  } predc_;
101 
102  extern struct predp_s {
103  double ccstop;
104  double barset;
105  double bargrw;
106  double barmin;
107  int mincor;
108  int maxcor;
109  int inibar;
110  } predp_;
111 
112  extern struct setden_s {
113  double maxdense;
114  double densgap;
115  int setlam;
116  int denslen;
117  } setden_;
118 
119  extern struct sprnod_s {
120  int psupn;
121  int ssupn;
122  int maxsnz;
123  } sprnod_;
124 
125  extern struct toler_s {
126  double tsdir;
127  double topt1;
128  double topt2;
129  double tfeas1;
130  double tfeas2;
131  double feas1;
132  double feas2;
133  double pinfs;
134  double dinfs;
135  double inftol;
136  int maxiter;
137  } toler_;
138 
139  extern int solver_(
140  double *obj, double *rhs, double *lbound, double *ubound,
141  /* Size dims_.mn working arrays */
142  double *diag, double *odiag,
143  /* Size dims_.mn primal values */
144  double *xs,
145  /* Size dims_.mn working arrays */
146  double *dxs, double *dxsn, double *up,
147  /* Size dims_.mn dual residuals */
148  double *dspr,
149  /* Size dims_.mn working arrays */
150  double *ddspr, double *ddsprn, double *dsup, double *ddsup,
151  double *ddsupn,
152  /* Size dims_.m dual values */
153  double *dv,
154  /* Size dims_.m working arrays */
155  double *ddv, double *ddvn, double *prinf,
156  /* Size dims_.mn working arrays */
157  double *upinf, double *duinf, double *scale,
158  /* Size dims_.cfree nonzero values */
159  double *nonzeros,
160  /* Size dims_.n working array */
161  int *vartyp,
162  /* Size dims_.m working array */
163  int *slktyp,
164  /* Size dims_.n1 column pointer */
165  int *colpnt,
166  /* Size dims_.mn working arrays */
167  int *ecolpnt, int *count, int *vcstat, int *pivots,
168  int *invprm, int *snhead, int *nodtyp, int *inta1,
169  int *prehis,
170  /* Size dims_.cfree row index */
171  int *rowidx,
172  /* Size dims_.rfree working array */
173  int *rindex,
174  /* Scalar termination code */
175  int *code,
176  /* Scalar optimum value */
177  double *opt,
178  int *iter, int *corect, int *fixn, int *dropn, int *fnzmax,
179  int *fnzmin, double *addobj, double *bigbou,
180  /* Practical +inf */
181  double *big,
182  int *ft);
183 }
184 
185 namespace {
186 
187  class problem_t {
188  public:
189 #pragma clang diagnostic push
190 #pragma clang diagnostic ignored "-Wunused-const-variable"
191  static constexpr double infinity = INFINITY;
192  // These are equivalent to the constants used by IBM ILOG
193  // CPLEX
194  static const int minimize = 1;
195  static const int maximize = -1;
196  static const char less_equal = 'L';
197  static const char equal = 'E';
198  static const char greater_equal = 'G';
199  static const char range = 'R';
200 #pragma clang diagnostic pop
201  protected:
202  bool _optimized;
203  bool _variable_named;
204 
205  std::vector<double> _rhs;
206  std::vector<char> _constraint_sense;
207  std::vector<double> _range_value;
208  std::vector<char *> _row_name;
209 
210  std::vector<double> _objective;
211  std::vector<double> _lower_bound;
212  std::vector<double> _upper_bound;
213  std::vector<char *> _column_name;
214 
215  std::vector<int> _coefficient_row;
216  std::vector<int> _coefficient_column;
217  std::vector<double> _coefficient_value;
218 
219  void clear_row(void)
220  {
221  _rhs.clear();
222  _constraint_sense.clear();
223  for (std::vector<char *>::const_iterator iterator =
224  _row_name.begin();
225  iterator != _row_name.end(); iterator++) {
226  delete [] *iterator;
227  }
228  _row_name.clear();
229  }
230  void clear_column(void)
231  {
232  _objective.clear();
233  _lower_bound.clear();
234  _upper_bound.clear();
235  for (std::vector<char *>::const_iterator iterator =
236  _column_name.begin();
237  iterator != _column_name.end(); iterator++) {
238  free(*iterator);
239  }
240  _column_name.clear();
241  }
242  void clear_coefficient(void)
243  {
244  _coefficient_row.clear();
245  _coefficient_column.clear();
246  _coefficient_value.clear();
247  }
248  void to_csr(std::vector<int> &column_pointer,
249  std::vector<int> &row_index,
250  std::vector<double> &nonzero_value,
251  const int index_start = 1)
252  {
253  // Convert from coordinate (COO) storage into compressed
254  // sparse row (CSR)
255 
256  std::vector<std::vector<std::pair<int, double> > >
257  column_index(_objective.size(),
258  std::vector<std::pair<int, double> >());
259 
260  std::vector<int>::const_iterator iterator_row =
261  _coefficient_row.begin();
262  std::vector<int>::const_iterator iterator_column =
263  _coefficient_column.begin();
264  std::vector<double>::const_iterator iterator_value =
265  _coefficient_value.begin();
266 
267  for (; iterator_value != _coefficient_value.end();
268  iterator_row++, iterator_column++, iterator_value++) {
269  column_index[*iterator_column].push_back(
270  std::pair<int, double>(
271  // Conversion into Fortran indexing
272  *iterator_row + index_start, *iterator_value));
273  }
274 
275  for (std::vector<std::vector<std::pair<int, double> > >::
276  iterator iterator_outer = column_index.begin();
277  iterator_outer != column_index.end(); iterator_outer++) {
278  // Conversion into Fortran indexing
279  column_pointer.push_back(row_index.size() + index_start);
280  std::sort(iterator_outer->begin(), iterator_outer->end());
281  for (std::vector<std::pair<int, double> >::const_iterator
282  iterator_inner = iterator_outer->begin();
283  iterator_inner != iterator_outer->end();
284  iterator_inner++) {
285  row_index.push_back(iterator_inner->first);
286  nonzero_value.push_back(iterator_inner->second);
287  }
288  }
289  // Conversion into Fortran indexing
290  column_pointer.push_back(row_index.size() + index_start);
291  }
292  public:
293  problem_t(const bool variable_named)
294  : _optimized(false), _variable_named(variable_named)
295  {
296  }
297  ~problem_t(void)
298  {
299  clear();
300  }
301  void clear(void)
302  {
303  clear_row();
304  clear_column();
305  clear_coefficient();
306  }
307  virtual int populate(void) = 0;
308  size_t nrow(void) const
309  {
310  return _rhs.size();
311  }
312  size_t ncolumn(void) const
313  {
314  return _objective.size();
315  }
316  void push_back_row(const char constraint_sense,
317  const double rhs)
318  {
319  _rhs.push_back(rhs);
320  _constraint_sense.push_back(constraint_sense);
321 
322  if (_variable_named) {
323  static const size_t name_length = 24;
324  char *name = new char[name_length];
325 
326  snprintf(name, name_length, "c%llu",
327  static_cast<unsigned long long>(_rhs.size()));
328  _row_name.push_back(name);
329  }
330  }
331  void push_back_row(const std::string &constraint_sense,
332  const double rhs)
333  {
334  char cplex_sense;
335 
336  if (constraint_sense == "<=") {
337  cplex_sense = 'L';
338  push_back_row(rhs, cplex_sense);
339  }
340  else if (constraint_sense == "==") {
341  cplex_sense = 'E';
342  push_back_row(rhs, cplex_sense);
343  }
344  else if (constraint_sense == ">=") {
345  cplex_sense = 'G';
346  push_back_row(rhs, cplex_sense);
347  }
348  else {
349  fprintf(stderr, "%s:%d: illegal sense (`%s')\n",
350  __FILE__, __LINE__, constraint_sense.c_str());
351  }
352  }
353  void push_back_column(const double objective,
354  const double lower_bound,
355  const double upper_bound)
356  {
357  _objective.push_back(objective);
358  _lower_bound.push_back(lower_bound);
359  _upper_bound.push_back(upper_bound);
360 
361  if (_variable_named) {
362  static const size_t name_length = 24;
363  char *name = new char[name_length];
364 
365  snprintf(name, name_length, "x%llu",
366  static_cast<unsigned long long>(
367  _objective.size()));
368  _column_name.push_back(name);
369  }
370  }
371  void push_back_coefficient(
372  const int row, const int column, const double value)
373  {
374  _coefficient_row.push_back(row);
375  _coefficient_column.push_back(column);
376  _coefficient_value.push_back(value);
377  }
378  virtual int optimize(void) = 0;
379  int optimize_primal_simplex(void)
380  {
381  return optimize();
382  }
383  int optimize_dual_simplex(void)
384  {
385  return optimize();
386  }
387  int optimize_barrier(void)
388  {
389  return optimize();
390  }
391  int optimize_network(void)
392  {
393  return optimize();
394  }
395  int optimize_sifting(void)
396  {
397  return optimize();
398  }
399  int optimize_concurrent(void)
400  {
401  return optimize();
402  }
403  int optimize_deterministic_concurrent(void)
404  {
405  return optimize();
406  }
407  //
408  virtual int solve(
409  int &solution_status, double &objective_value,
410  std::vector<double> &variable_primal,
411  std::vector<double> &variable_dual,
412  std::vector<double> &variable_slack_surplus,
413  std::vector<double> &reduced_cost) = 0;
414  int solve(
415  double &objective_value,
416  std::vector<double> &variable_primal,
417  std::vector<double> &variable_dual,
418  std::vector<double> &variable_slack_surplus,
419  std::vector<double> &reduced_cost)
420  {
421  int solution_status;
422 
423  return solve(solution_status, objective_value,
424  variable_primal, variable_dual,
425  variable_slack_surplus, reduced_cost);
426  }
427  int solve(
428  std::vector<double> &variable_primal,
429  std::vector<double> &variable_dual,
430  std::vector<double> &variable_slack_surplus,
431  std::vector<double> &reduced_cost)
432  {
433  int solution_status;
434  double objective_value;
435 
436  return solve(solution_status, objective_value,
437  variable_primal, variable_dual,
438  variable_slack_surplus, reduced_cost);
439  }
440  virtual int solve(
441  int &solution_status, double &objective_value,
442  std::vector<double> &variable_primal,
443  std::vector<double> &variable_dual)
444  {
445  std::vector<double> variable_slack_surplus;
446  std::vector<double> reduced_cost;
447 
448  return solve(solution_status, objective_value,
449  variable_primal, variable_dual,
450  variable_slack_surplus, reduced_cost);
451  }
452  int solve(
453  std::vector<double> &variable_primal,
454  std::vector<double> &variable_dual)
455  {
456  int solution_status;
457  double objective_value;
458 
459  return solve(solution_status, objective_value, variable_primal,
460  variable_dual);
461  }
462  int solve(
463  std::vector<double> &variable_primal)
464  {
465  std::vector<double> variable_dual;
466 
467  return solve(variable_primal, variable_dual);
468  }
469  };
470 
471  class environment_t {
472  protected:
473  std::vector<problem_t *> _problem;
474  };
475 
476 #ifndef BPMPD_INFINITY_BOUND
477 #define BPMPD_INFINITY_BOUND 1e+30
478 #endif // BPMPD_INFINITY_BOUND
479 
480 #ifndef BPMPD_VERSION_STRING
481 #define BPMPD_VERSION_STRING "Version 2.11 (1996 December)"
482 #endif // BPMPD_VERSION_STRING
483 
484  class bpmpd_environment_t;
485 
486  class bpmpd_problem_t : public problem_t {
487  public:
488 #pragma clang diagnostic push
489 #pragma clang diagnostic ignored "-Wunused-const-variable"
490  static constexpr double infinity = BPMPD_INFINITY_BOUND;
491 #pragma clang diagnostic pop
492  protected:
493  double _objective_sense;
494  double _objective_value;
495  std::vector<double> _variable_primal;
496  std::vector<double> _variable_dual;
497  int _solution_status;
498  private:
499  int ampl_solution_status(const int termination_code)
500  {
501  switch (termination_code) {
502  // General memory limit (no solution)
503  case -2: return 520;
504  // Memory limit during iterations
505  case -1: return 510;
506  // No optimum
507  case 1: return 506;
508  // Optimal solution
509  case 2: return 0;
510  // Primal infeasible
511  case 3: return 503;
512  // Dual infeasible
513  case 4: return 503;
514  default:
515  fprintf(stderr, "%s:%d: error: unknown termination code "
516  "%d\n", __FILE__, __LINE__, termination_code);
517  return 500;
518  }
519  fprintf(stderr, "%s:%d: %d\n", __FILE__, __LINE__,
520  termination_code);
521  }
522  void set_bpmpd_parameter(void)
523  {
524  // Set the parameter as in subroutine BPMAIN
525 
526  setden_.maxdense = 0.15;
527  setden_.densgap = 3.00;
528  setden_.setlam = 0;
529  factor_.supdens = 250;
530  setden_.denslen = 10;
531 
532  mscal_.varadd = 1e-12;
533  mscal_.slkadd = 1e+16;
534  mscal_.scfree = 1.1e-6;
535 
536  factor_.tpiv1 = 1e-3;
537  factor_.tpiv2 = 1e-8;
538  factor_.tabs = 1e-12;
539  factor_.trabs = 1e-15;
540  factor_.lam = 1e-5;
541  factor_.tfind = 25;
542  factor_.order = 2;
543 
544  sprnod_.psupn = 3;
545  sprnod_.ssupn = 4;
546  sprnod_.maxsnz = 9999999;
547 
548  toler_.tsdir = 1e-16;
549  toler_.topt1 = 1e-8;
550  toler_.topt2 = 1e-16;
551  toler_.tfeas1 = 1e-7;
552  toler_.tfeas2 = 1e-7;
553  toler_.feas1 = 1e-2;
554  toler_.feas2 = 1e-2;
555  toler_.pinfs = 1e-6;
556  toler_.dinfs = 1e-6;
557  toler_.inftol = 1e+4;
558  toler_.maxiter = 99;
559 
560  numer_.tplus = 1e-11;
561  numer_.tzer = 1e-35;
562 
563  itref_.tresx = 1e-9;
564  itref_.tresy = 1e-9;
565  itref_.maxref = 5;
566 
567  ascal_.objnor = 1e+2;
568  ascal_.rhsnor = 0;
569  ascal_.scdiff = 1;
570  ascal_.scalmet = 2;
571  ascal_.scpass = 5;
572 
573  predp_.ccstop = 1.01;
574  predp_.barset = 2.50e-1;
575  predp_.bargrw = 1.00e+2;
576  predp_.barmin = 1.00e-10;
577  predp_.mincor = 1;
578  predp_.maxcor = 1;
579  predp_.inibar = 0;
580 
581  predc_.target = 9e-2;
582  predc_.tsmall = 2e-1;
583  predc_.tlarge = 2e+1;
584  predc_.center = 5;
585  predc_.corstp = 1.01;
586  predc_.mincc = 0;
587  predc_.maxcc = 9;
588 
589  param_.palpha = 0.999;
590  param_.dalpha = 0.999;
591 
592  drop_.tfixvar = 1e-16;
593  drop_.tfixslack = 1e-16;
594  drop_.slklim = 1e-16;
595 
596  initv_.prmin = 100;
597  initv_.upmax = 50000;
598  initv_.dumin = 100;
599  initv_.stamet = 2;
600  initv_.safmet = -3;
601  initv_.premet = 511;
602  initv_.regul = 0;
603 
604  compl_.climit = 1;
605  compl_.ccorr = 1e-5;
606  }
607  void append_constraint_sense_bound(
608  std::vector<double> &lower_bound_bpmpd,
609  std::vector<double> &upper_bound_bpmpd)
610  {
611  for (std::vector<char>::const_iterator iterator =
612  _constraint_sense.begin();
613  iterator != _constraint_sense.end(); iterator++) {
614  switch (*iterator) {
615  case less_equal:
616  lower_bound_bpmpd.push_back(-BPMPD_INFINITY_BOUND);
617  upper_bound_bpmpd.push_back(0);
618  break;
619  case equal:
620  lower_bound_bpmpd.push_back(0);
621  upper_bound_bpmpd.push_back(0);
622  break;
623  case greater_equal:
624  lower_bound_bpmpd.push_back(0);
625  upper_bound_bpmpd.push_back(BPMPD_INFINITY_BOUND);
626  break;
627  case range:
628  {
629  const size_t index =
630  iterator - _constraint_sense.begin();
631 
632  lower_bound_bpmpd.push_back(0);
633  upper_bound_bpmpd.push_back(_range_value[index] -
634  _rhs[index]);
635  }
636  break;
637  }
638  }
639  lower_bound_bpmpd.reserve(dims_.mn);
640  lower_bound_bpmpd.insert(lower_bound_bpmpd.end(),
641  _lower_bound.begin(),
642  _lower_bound.end());
643  upper_bound_bpmpd.reserve(dims_.mn);
644  upper_bound_bpmpd.insert(upper_bound_bpmpd.end(),
645  _upper_bound.begin(),
646  _upper_bound.end());
647  }
648  protected:
649  int populate(void)
650  {
651  return 0;
652  }
653  public:
654  bpmpd_problem_t(void)
655  : problem_t(false), _objective_sense(1.0),
656  _objective_value(NAN)
657  {
658  }
659  inline size_t nrow(void) const
660  {
661  return dims_.m;
662  }
663  inline size_t ncolumn(void) const
664  {
665  return dims_.n;
666  }
667  inline void set_objective_sense(int sense)
668  {
669  _objective_sense = sense;
670 
671  // This will be multiplied to the objective coefficients
672  // (i.e. sign flip when sense = -1 for maximization)
673  }
674  inline void save(std::string filename)
675  {
676  // MPS save?
677  }
678  void push_back_column(const double objective,
679  const double lower_bound = 0,
680  const double upper_bound = BPMPD_INFINITY_BOUND)
681  {
682  problem_t::push_back_column(objective, lower_bound,
683  upper_bound);
684  }
685  void set_size(const size_t nonzero_value_size,
686  const double mf = 6.0, const size_t ma = 0)
687  {
688  dims_.n = _objective.size();
689  dims_.m = _rhs.size();
690  dims_.mn = dims_.m + dims_.n;
691  dims_.n1 = dims_.n + 1;
692 
693  dims_.nz = nonzero_value_size;
694 
695  // Adapted from the AMPL interface
696  // http://www.netlib.org/ampl/solvers/bpmpd/
697 
698  const size_t rp_23 = 4 * dims_.m + 18 * dims_.mn;
699 
700  dims_.cfree = static_cast<int>(
701  std::max(2.0, mf) * (rp_23 + dims_.nz)) +
702  std::max(static_cast<size_t>(0), ma);
703  dims_.rfree = ((dims_.cfree + rp_23) >> 1) + 11 * dims_.m +
704  8 * dims_.n;
705  }
706  int optimize(void)
707  {
708  // Usually referred to as the variable "IA" for the CSR format
709  std::vector<int> column_pointer;
710  // Usually referred to as the variable "JA" for the CSR format
711  std::vector<int> row_index;
712  // Usually referred to as the variable "A" for the CSR format
713  std::vector<double> nonzero_value;
714 
715  to_csr(column_pointer, row_index, nonzero_value);
716  std::transform(_objective.begin(), _objective.end(),
717  _objective.begin(),
718  std::bind1st(std::multiplies<double>(),
719  _objective_sense));
720 
721  // Try 1x, 2x, and 4x the default memory allocation
722  for (size_t i = 0; i < 3; i++) {
723  set_size(nonzero_value.size(), 6.0 * (1 << i));
724 
725  nonzero_value.resize(dims_.cfree);
726  row_index.resize(dims_.cfree);
727 
728  set_bpmpd_parameter();
729 
730  std::vector<double> diag(dims_.mn, 0);
731  std::vector<double> odiag(dims_.mn, 0);
732  std::vector<double> dxs(dims_.mn, 0);
733  std::vector<double> dxsn(dims_.mn, 0);
734  std::vector<double> up(dims_.mn, 0);
735  std::vector<double> dual_residual(dims_.mn, 0);
736  std::vector<double> ddspr(dims_.mn, 0);
737  std::vector<double> ddsprn(dims_.mn, 0);
738  std::vector<double> dsup(dims_.mn, 0);
739  std::vector<double> ddsup(dims_.mn, 0);
740  std::vector<double> ddsupn(dims_.mn, 0);
741  std::vector<double> ddv(dims_.m, 0);
742  std::vector<double> ddvn(dims_.m, 0);
743  std::vector<double> prinf(dims_.m, 0);
744  std::vector<double> upinf(dims_.mn, 0);
745  std::vector<double> duinf(dims_.mn, 0);
746  std::vector<double> scale(dims_.mn, 0);
747  std::vector<int> vartyp(dims_.n, 0);
748  std::vector<int> slktyp(dims_.m, 0);
749  std::vector<int> colpnt(dims_.n1, 0);
750  std::vector<int> ecolpnt(dims_.mn, 0);
751  std::vector<int> count(dims_.mn, 0);
752  std::vector<int> vcstat(dims_.mn, 0);
753  std::vector<int> pivots(dims_.mn, 0);
754  std::vector<int> invprm(dims_.mn, 0);
755  std::vector<int> snhead(dims_.mn, 0);
756  std::vector<int> nodtyp(dims_.mn, 0);
757  std::vector<int> inta1(dims_.mn, 0);
758  std::vector<int> prehis(dims_.mn, 0);
759  std::vector<int> rindex(dims_.rfree, 0);
760  int termination_code;
761  int iter;
762  int correct;
763  int fixn;
764  int dropn;
765  int fnzmax = 0;
766  int fnzmin = -1;
767  double addobj = 0;
768  // Numerical limit of bounds to be ignored
769  double bigbou = 1e+15;
770  double infinity_copy = BPMPD_INFINITY_BOUND;
771  int ft;
772 
773  _variable_primal.resize(dims_.mn);
774  _variable_dual.resize(dims_.m);
775 
776  std::vector<double> lower_bound_bpmpd = _lower_bound;
777  std::vector<double> upper_bound_bpmpd = _upper_bound;
778 
779  append_constraint_sense_bound(lower_bound_bpmpd,
780  upper_bound_bpmpd);
781 
782  solver_(&_objective[0], &_rhs[0], &lower_bound_bpmpd[0],
783  &upper_bound_bpmpd[0], &diag[0], &odiag[0],
784  &_variable_primal[0], &dxs[0], &dxsn[0], &up[0],
785  &dual_residual[0], &ddspr[0], &ddsprn[0],
786  &dsup[0], &ddsup[0], &ddsupn[0],
787  &_variable_dual[0], &ddv[0], &ddvn[0], &prinf[0],
788  &upinf[0], &duinf[0], &scale[0],
789  &nonzero_value[0], &vartyp[0], &slktyp[0],
790  &column_pointer[0], &ecolpnt[0], &count[0],
791  &vcstat[0], &pivots[0], &invprm[0], &snhead[0],
792  &nodtyp[0], &inta1[0], &prehis[0], &row_index[0],
793  &rindex[0], &termination_code, &_objective_value,
794  &iter, &correct, &fixn, &dropn, &fnzmax, &fnzmin,
795  &addobj, &bigbou, &infinity_copy, &ft);
796 
797  _objective_value *= _objective_sense;
798  _solution_status = ampl_solution_status(termination_code);
799  if (termination_code != -2) {
800  // No out-of-memory errors
801  break;
802  }
803  }
804 
805  return _solution_status == 0 ? 0 : 1;
806  }
807  int solve(
808  int &solution_status, double &objective_value,
809  std::vector<double> &variable_primal,
810  std::vector<double> &variable_dual,
811  std::vector<double> &variable_slack_surplus,
812  std::vector<double> &reduced_cost)
813  {
814  // This set of solution is not implemented yet (or readily
815  // available from BPMPD)
816 
817  return 1;
818  }
819  int solve(
820  int &solution_status, double &objective_value,
821  std::vector<double> &variable_primal,
822  std::vector<double> &variable_dual)
823  {
824  variable_primal = std::vector<double>(
825  _variable_primal.begin(),
826  _variable_primal.begin() + _objective.size());
827  variable_dual = _variable_dual;
828 
829  return 0;
830  }
831  friend class bpmpd_environment_t;
832  };
833 
834  class bpmpd_environment_t : public environment_t {
835  public:
836  bpmpd_environment_t(void)
837  {
838  }
839  ~bpmpd_environment_t(void)
840  {
841  }
842  int set_verbose(void);
843  int set_data_checking(void);
844  inline std::string version_str(void) const
845  {
846  return BPMPD_VERSION_STRING;
847  }
848  bpmpd_problem_t problem(std::string name = "")
849  {
850  return bpmpd_problem_t();
851  }
852  };
853 
854 }
855 
856 namespace {
857 
858  double angular_range_reduce(const double x)
859  {
860  if (!std::isfinite(x)) {
861  return NAN;
862  }
863 
864  static const double cody_waite_x_max = 1608.4954386379741381;
865  static const double two_pi_0 = 6.2831853071795649157;
866  static const double two_pi_1 = 2.1561211432631314669e-14;
867  static const double two_pi_2 = 1.1615423895917441336e-27;
868  double ret = 0;
869 
870  if (x >= -cody_waite_x_max && x <= cody_waite_x_max) {
871  static const double inverse_two_pi =
872  0.15915494309189534197;
873  const double k = rint(x * inverse_two_pi);
874  ret = ((x - (k * two_pi_0)) - k * two_pi_1) -
875  k * two_pi_2;
876  }
877  else {
878  ret = normalizedPhi(ret);
879  }
880  if (ret == -M_PI) {
881  ret = M_PI;
882  }
883 
884  return ret;
885  }
886 
887  double hermite_h_normalized(const size_t n, const double x)
888  {
889  double y;
890 
891  switch (n) {
892  case 3: y = -3.913998411780905*x + 2.6093322745206033*std::pow(x,3); break;
893  case 5: y = 4.931174490213579*x - 6.574899320284771*std::pow(x,3) + 1.3149798640569543*std::pow(x,5); break;
894  case 7: y = -5.773117374387059*x + 11.546234748774118*std::pow(x,3) - 4.618493899509647*std::pow(x,5) + 0.43985656185806166*std::pow(x,7); break;
895  case 9: y = 6.507479403136423*x - 17.353278408363792*std::pow(x,3) + 10.411967045018276*std::pow(x,5) - 1.9832318180987192*std::pow(x,7) + 0.11017954544992885*std::pow(x,9); break;
896  case 11: y = -7.167191940825306*x + 23.89063980275102*std::pow(x,3) - 19.112511842200817*std::pow(x,5) + 5.460717669200234*std::pow(x,7) - 0.6067464076889149*std::pow(x,9) + 0.02206350573414236*std::pow(x,11); break;
897  case 13: y = 7.771206704387521*x - 31.084826817550084*std::pow(x,3) + 31.084826817550084*std::pow(x,5) - 11.841838787638126*std::pow(x,7) + 1.9736397979396878*std::pow(x,9) - 0.14353743985015913*std::pow(x,11) + 0.0036804471756451056*std::pow(x,13); break;
898  case 15: y = -8.331608118589472*x + 38.88083788675087*std::pow(x,3) - 46.65700546410104*std::pow(x,5) + 22.217621649571925*std::pow(x,7) - 4.9372492554604275*std::pow(x,9) + 0.5386090096865921*std::pow(x,11) - 0.027620974855722673*std::pow(x,13) + 0.00052611380677567*std::pow(x,15); break;
899  case 17: y = 8.856659222944476*x - 47.23551585570387*std::pow(x,3) + 66.12972219798543*std::pow(x,5) - 37.7884126845631*std::pow(x,7) + 10.496781301267527*std::pow(x,9) - 1.5268045529116403*std::pow(x,11) + 0.11744650407012618*std::pow(x,13) - 0.004474152536004807*std::pow(x,15) + 0.0000657963608236001*std::pow(x,17); break;
900  default: y = 0;
901  }
902 
903  return y;
904  }
905 
906 }
907 
909  {
910  static const size_t ncms_hcal_edge_pseudorapidity = 82 + 1;
911  static const double cms_hcal_edge_pseudorapidity[
912  ncms_hcal_edge_pseudorapidity] = {
913  -5.191, -4.889, -4.716, -4.538, -4.363, -4.191, -4.013,
914  -3.839, -3.664, -3.489, -3.314, -3.139, -2.964, -2.853,
915  -2.650, -2.500, -2.322, -2.172, -2.043, -1.930, -1.830,
916  -1.740, -1.653, -1.566, -1.479, -1.392, -1.305, -1.218,
917  -1.131, -1.044, -0.957, -0.879, -0.783, -0.696, -0.609,
918  -0.522, -0.435, -0.348, -0.261, -0.174, -0.087,
919  0.000,
920  0.087, 0.174, 0.261, 0.348, 0.435, 0.522, 0.609,
921  0.696, 0.783, 0.879, 0.957, 1.044, 1.131, 1.218,
922  1.305, 1.392, 1.479, 1.566, 1.653, 1.740, 1.830,
923  1.930, 2.043, 2.172, 2.322, 2.500, 2.650, 2.853,
924  2.964, 3.139, 3.314, 3.489, 3.664, 3.839, 4.013,
925  4.191, 4.363, 4.538, 4.716, 4.889, 5.191
926  };
927 
928  _cms_hcal_edge_pseudorapidity = std::vector<double>(
929  cms_hcal_edge_pseudorapidity,
930  cms_hcal_edge_pseudorapidity +
931  ncms_hcal_edge_pseudorapidity);
932 
933  static const size_t ncms_ecal_edge_pseudorapidity = 344 + 1;
934 
935  for (size_t i = 0; i < ncms_ecal_edge_pseudorapidity; i++) {
936  _cms_ecal_edge_pseudorapidity.push_back(
937  i * (2 * 2.9928 /
938  (ncms_ecal_edge_pseudorapidity - 1)) -
939  2.9928);
940  }
941  }
943  {
944  _perp_fourier = new boost::multi_array<double, 4>(
945  boost::extents[_edge_pseudorapidity.size() - 1]
946  [nreduced_particle_flow_id][nfourier][2]);
947  }
949  {
950  delete _perp_fourier;
951  }
953  {
954  std::fill(_perp_fourier->data(),
955  _perp_fourier->data() +
956  _perp_fourier->num_elements(),
957  0);
958 
959  for (std::vector<particle_t>::const_iterator iterator =
960  _event.begin();
961  iterator != _event.end(); iterator++) {
962  const unsigned int reduced_id =
963  iterator->reduced_particle_flow_id;
964 
965  for (size_t k = 1; k < _edge_pseudorapidity.size();
966  k++) {
967  if (iterator->momentum.Eta() >=
968  _edge_pseudorapidity[k - 1] &&
969  iterator->momentum.Eta() <
970  _edge_pseudorapidity[k]) {
971  const double azimuth =
972  iterator->momentum.Phi();
973 
974  for (size_t l = 0; l < nfourier; l++) {
975  (*_perp_fourier)[k - 1][reduced_id]
976  [l][0] +=
977  iterator->momentum.Pt() *
978  cos(l * azimuth);
979  (*_perp_fourier)[k - 1][reduced_id]
980  [l][1] +=
981  iterator->momentum.Pt() *
982  sin(l * azimuth);
983  }
984  }
985  }
986  }
987  }
989  {
990  const size_t nfeature = 2 * nfourier - 1;
991 
992  _feature.resize(nfeature);
993 
994  // Scale factor to get 95% of the coefficient below 1.0
995  // (where however one order of magnitude tolerance is
996  // acceptable). This is valid for nfourier < 18 (where
997  // interference behavior with the HF geometry starts to
998  // appear)
999 
1000  std::vector<double> scale(nfourier, 1.0 / 200.0);
1001 
1002  if (nfourier >= 1) {
1003  scale[0] = 1.0 / 5400.0;
1004  }
1005  if (nfourier >= 2) {
1006  scale[1] = 1.0 / 130.0;
1007  }
1008  if (nfourier >= 3) {
1009  scale[2] = 1.0 / 220.0;
1010  }
1011 
1012  const size_t index_edge_end =
1013  _edge_pseudorapidity.size() - 2;
1014 
1015  _feature[0] = 0;
1016  for (size_t j = 0; j < nreduced_particle_flow_id; j++) {
1017  _feature[0] += scale[0] *
1018  ((*_perp_fourier)[0 ][j][0][0] +
1019  (*_perp_fourier)[index_edge_end][j][0][0]);
1020  }
1021 
1022  for (size_t k = 1; k < nfourier; k++) {
1023  _feature[2 * k - 1] = 0;
1024  for (size_t j = 0; j < nreduced_particle_flow_id; j++) {
1025  _feature[2 * k - 1] += scale[k] *
1026  ((*_perp_fourier)[0 ][j][k][0] +
1027  (*_perp_fourier)[index_edge_end][j][k][0]);
1028  }
1029  _feature[2 * k] = 0;
1030  for (size_t j = 0; j < nreduced_particle_flow_id; j++) {
1031  _feature[2 * k] += scale[k] *
1032  ((*_perp_fourier)[0 ][j][k][1] +
1033  (*_perp_fourier)[index_edge_end][j][k][1]);
1034  }
1035  }
1036 
1037 
1038 #if 0
1039  const double event_plane = atan2(_feature[4], _feature[3]);
1040  const double v2 =
1041  sqrt(_feature[3] * _feature[3] +
1042  _feature[4] * _feature[4]) / _feature[0];
1043 #endif
1044  }
1046  {
1047  // Make the Voronoi diagram
1048 
1049  voronoi_diagram_t diagram;
1050 
1051  // Reverse Voronoi face lookup
1052 #ifdef HAVE_SPARSEHASH
1053  // The "empty" or default value of the hash table
1054  const voronoi_diagram_t::Face face_empty;
1055  google::dense_hash_map<voronoi_diagram_t::Face_handle,
1056  size_t, hash<voronoi_diagram_t::Face_handle> >
1057  face_index;
1058 
1059  face_index.set_empty_key(face_empty);
1060 #else // HAVE_SPARSEHASH
1061  std::map<voronoi_diagram_t::Face_handle, size_t>
1062  face_index;
1063 #endif // HAVE_SPARSEHASH
1064 
1065  for (std::vector<particle_t>::const_iterator iterator =
1066  _event.begin();
1067  iterator != _event.end(); iterator++) {
1068  // Make two additional replicas with azimuth +/- 2 pi
1069  // (and use only the middle) to mimick the azimuthal
1070  // cyclicity
1071  for (int k = -1; k <= 1; k++) {
1072  const point_2d_t p(
1073  iterator->momentum.Eta(),
1074  iterator->momentum.Phi() +
1075  k * (2 * M_PI));
1076  const voronoi_diagram_t::Face_handle handle =
1077  diagram.insert(p);
1078 
1079  face_index[handle] = iterator - _event.begin();
1080  }
1081  }
1082 
1083  // Extract the Voronoi cells as polygon and calculate the
1084  // area associated with individual particles
1085 
1086  for (std::vector<particle_t>::iterator iterator =
1087  _event.begin();
1088  iterator != _event.end(); iterator++) {
1089  const voronoi_diagram_t::Locate_result result =
1090  diagram.locate(*iterator);
1091  const voronoi_diagram_t::Face_handle *face =
1092  boost::get<voronoi_diagram_t::Face_handle>(
1093  &result);
1094  double polygon_area;
1095 
1096  if (face != NULL) {
1097  voronoi_diagram_t::Ccb_halfedge_circulator
1098  circulator_start = (*face)->outer_ccb();
1099  bool unbounded = false;
1100  polygon_t polygon;
1101 
1102  voronoi_diagram_t::Ccb_halfedge_circulator
1103  circulator = circulator_start;
1104 
1105  // Circle around the edges and extract the polygon
1106  // vertices
1107  do {
1108  if (circulator->has_target()) {
1109  polygon.push_back(
1110  circulator->target()->point());
1111  _event[face_index[*face]].incident.
1112  insert(
1113  _event.begin() +
1114  face_index[circulator->twin()->
1115  face()]);
1116  }
1117  else {
1118  unbounded = true;
1119  break;
1120  }
1121  }
1122  while (++circulator != circulator_start);
1123  if (unbounded) {
1124  polygon_area = INFINITY;
1125  }
1126  else {
1127  polygon_area = polygon.area();
1128  }
1129  }
1130  else {
1131  polygon_area = NAN;
1132  }
1133  iterator->area = fabs(polygon_area);
1134  }
1135  }
1137  {
1138  for (std::vector<particle_t>::iterator iterator =
1139  _event.begin();
1140  iterator != _event.end(); iterator++) {
1141  int predictor_index = -1;
1142  int interpolation_index = -1;
1143  double density = 0;
1144  double pred_0 = 0;
1145 
1146  for (size_t l = 1; l < _edge_pseudorapidity.size(); l++) {
1147  if (iterator->momentum.Eta() >=
1148  _edge_pseudorapidity[l - 1] &&
1149  iterator->momentum.Eta() <
1150  _edge_pseudorapidity[l]) {
1151  predictor_index = l - 1;
1152  }
1153  }
1154 
1155  for (size_t j = 0; j < nreduced_particle_flow_id; j++) {
1156  if (j == 2) {
1157  // HCAL
1158  for (size_t l = 1;
1159  l < _cms_hcal_edge_pseudorapidity.size(); l++) {
1160  if (iterator->momentum.Eta() >=
1161  _cms_hcal_edge_pseudorapidity[l - 1] &&
1162  iterator->momentum.Eta() <
1163  _cms_hcal_edge_pseudorapidity[l]) {
1164  interpolation_index = l - 1;
1165  }
1166  }
1167  }
1168  else {
1169  // Tracks or ECAL clusters
1170  for (size_t l = 1;
1171  l < _cms_ecal_edge_pseudorapidity.size(); l++) {
1172  if (iterator->momentum.Eta() >=
1173  _cms_ecal_edge_pseudorapidity[l - 1] &&
1174  iterator->momentum.Eta() <
1175  _cms_ecal_edge_pseudorapidity[l]) {
1176  interpolation_index = l - 1;
1177  }
1178  }
1179  }
1180 
1181  if (predictor_index >= 0 && interpolation_index >= 0) {
1182  // Calculate the aggregated prediction and
1183  // interpolation for the pseudorapidity segment
1184 
1185  const double azimuth = iterator->momentum.Phi();
1186  const float (*p)[2][82] =
1187 #ifdef STANDALONE
1188  ue_predictor_pf[j][predictor_index]
1189 #else // STANDALONE
1190  ue->ue_predictor_pf[j][predictor_index]
1191 #endif // STANDALONE
1192  ;
1193  double pred = 0;
1194 
1195  for (size_t l = 0; l < nfourier; l++) {
1196  const size_t norder = l == 0 ? 9 : 1;
1197 
1198  for (size_t m = 0; m < 2; m++) {
1199  float u = p[l][m][0];
1200 
1201  for (size_t n = 0; n < 2 * nfourier - 1; n++) {
1202  if ((l == 0 && n == 0) || (l == 2 && (n == 3 || n == 4))) {
1203  u += p[l][m][9 * n + 1] * _feature[n];
1204  for (size_t o = 2; o < norder + 1; o++) {
1205  u += p[l][m][9 * n + o] *
1206  hermite_h_normalized(
1207  2 * o - 1, _feature[n]) *
1208  exp(-_feature[n] * _feature[n]);
1209  }
1210  }
1211  }
1212 
1213  pred += u * (l == 0 ? 1.0 : 2.0) *
1214  (m == 0 ? cos(l * azimuth) :
1215  sin(l * azimuth));
1216  if (l == 0 && m == 0) {
1217  pred_0 += u /
1218  (2.0 * M_PI *
1219  (_edge_pseudorapidity[predictor_index + 1] -
1220  _edge_pseudorapidity[predictor_index]));
1221  }
1222  }
1223  }
1224 
1225  double interp = 0;
1226 
1227 #ifdef STANDALONE
1228  if (j == 0) {
1229  interp =
1230  ue_interpolation_pf0[predictor_index][
1231  interpolation_index];
1232  }
1233  else if (j == 1) {
1234  interp =
1235  ue_interpolation_pf1[predictor_index][
1236  interpolation_index];
1237  }
1238  else if (j == 2) {
1239  interp =
1240  ue_interpolation_pf2[predictor_index][
1241  interpolation_index];
1242  }
1243 #else // STANDALONE
1244  if (j == 0) {
1245  interp =
1246  ue->ue_interpolation_pf0[predictor_index][
1247  interpolation_index];
1248  }
1249  else if (j == 1) {
1250  interp =
1251  ue->ue_interpolation_pf1[predictor_index][
1252  interpolation_index];
1253  }
1254  else if (j == 2) {
1255  interp =
1256  ue->ue_interpolation_pf2[predictor_index][
1257  interpolation_index];
1258  }
1259 #endif // STANDALONE
1260  // Interpolate down to the finely binned
1261  // pseudorapidity
1262 
1263  density += pred /
1264  (2.0 * M_PI *
1265  (_edge_pseudorapidity[predictor_index + 1] -
1266  _edge_pseudorapidity[predictor_index])) *
1267  interp;
1268  }
1269  }
1270 
1271  if (std::isfinite(iterator->area) && density >= 0) {
1272  // Subtract the PF candidate by density times
1273  // Voronoi cell area
1274  iterator->momentum_perp_subtracted =
1275  iterator->momentum.Pt() -
1276  density * iterator->area;
1277  }
1278  else {
1279  iterator->momentum_perp_subtracted =
1280  iterator->momentum.Pt();
1281  }
1282  iterator->momentum_perp_subtracted_unequalized =
1283  iterator->momentum_perp_subtracted;
1284  }
1285  }
1287  {
1288  boost::multi_array<double, 2> radial_distance_square(
1289  boost::extents[_event.size()][_event.size()]);
1290 
1291  for (std::vector<particle_t>::const_iterator
1292  iterator_outer = _event.begin();
1293  iterator_outer != _event.end(); iterator_outer++) {
1294  radial_distance_square
1295  [iterator_outer - _event.begin()]
1296  [iterator_outer - _event.begin()] = 0;
1297 
1298  for (std::vector<particle_t>::const_iterator
1299  iterator_inner = _event.begin();
1300  iterator_inner != iterator_outer;
1301  iterator_inner++) {
1302  const double deta = iterator_outer->momentum.Eta() -
1303  iterator_inner->momentum.Eta();
1304  const double dphi = angular_range_reduce(
1305  iterator_outer->momentum.Phi() -
1306  iterator_inner->momentum.Phi());
1307 
1308  radial_distance_square
1309  [iterator_outer - _event.begin()]
1310  [iterator_inner - _event.begin()] =
1311  deta * deta + dphi * dphi;
1312  radial_distance_square
1313  [iterator_inner - _event.begin()]
1314  [iterator_outer - _event.begin()] =
1315  radial_distance_square
1316  [iterator_outer - _event.begin()]
1317  [iterator_inner - _event.begin()];
1318  }
1319  }
1320 
1321  _active.clear();
1322 
1323  for (std::vector<particle_t>::const_iterator
1324  iterator_outer = _event.begin();
1325  iterator_outer != _event.end(); iterator_outer++) {
1326  double incident_area_sum = iterator_outer->area;
1327 
1328  for (std::set<std::vector<particle_t>::iterator>::
1329  const_iterator iterator_inner =
1330  iterator_outer->incident.begin();
1331  iterator_inner !=
1332  iterator_outer->incident.end();
1333  iterator_inner++) {
1334  incident_area_sum += (*iterator_inner)->area;
1335  }
1336  _active.push_back(incident_area_sum < 2.0);
1337  }
1338 
1339  _recombine.clear();
1340  _recombine_index = std::vector<std::vector<size_t> >(
1341  _event.size(), std::vector<size_t>());
1342  _recombine_unsigned = std::vector<std::vector<size_t> >(
1343  _event.size(), std::vector<size_t>());
1344  _recombine_tie.clear();
1345 
1346  // 36 cells corresponds to ~ 3 layers, note that for
1347  // hexagonal tiling, cell in proximity = 3 * layer *
1348  // (layer + 1)
1349  static const size_t npair_max = 36;
1350 
1351  for (size_t i = 0; i < _event.size(); i++) {
1352  for (size_t j = 0; j < _event.size(); j++) {
1353  const bool active_i_j = _active[i] && _active[j];
1354  const size_t incident_count =
1355  _event[i].incident.count(_event.begin() + j) +
1356  _event[j].incident.count(_event.begin() + i);
1357 
1358  if (active_i_j &&
1359  (radial_distance_square[i][j] <
1360  _radial_distance_square_max ||
1361  incident_count > 0)) {
1362  _recombine_unsigned[i].push_back(j);
1363  }
1364  }
1365 
1366  if (_event[i].momentum_perp_subtracted < 0) {
1367  std::vector<double> radial_distance_square_list;
1368 
1369  for (std::vector<size_t>::const_iterator iterator =
1370  _recombine_unsigned[i].begin();
1371  iterator != _recombine_unsigned[i].end();
1372  iterator++) {
1373  const size_t j = *iterator;
1374 
1375  if (_event[j].momentum_perp_subtracted > 0) {
1376  radial_distance_square_list.push_back(
1377  radial_distance_square[i][j]);
1378  }
1379  }
1380 
1381  double radial_distance_square_max_equalization_cut =
1382  _radial_distance_square_max;
1383 
1384  if (radial_distance_square_list.size() >= npair_max) {
1385  std::sort(radial_distance_square_list.begin(),
1386  radial_distance_square_list.end());
1387  radial_distance_square_max_equalization_cut =
1388  radial_distance_square_list[npair_max - 1];
1389  }
1390 
1391  for (std::vector<size_t>::const_iterator iterator =
1392  _recombine_unsigned[i].begin();
1393  iterator != _recombine_unsigned[i].end();
1394  iterator++) {
1395  const size_t j = *iterator;
1396 
1397  if (_event[j].momentum_perp_subtracted > 0 &&
1398  radial_distance_square[i][j] <
1399  radial_distance_square_max_equalization_cut) {
1400  _recombine_index[j].push_back(
1401  _recombine.size());
1402  _recombine_index[i].push_back(
1403  _recombine.size());
1404  _recombine.push_back(
1405  std::pair<size_t, size_t>(i, j));
1406  _recombine_tie.push_back(
1407  radial_distance_square[i][j] /
1408  _radial_distance_square_max);
1409  }
1410  }
1411  }
1412  }
1413  }
1414  void VoronoiAlgorithm::lp_populate(void *lp_problem)
1415  {
1416  bpmpd_problem_t *p = reinterpret_cast<bpmpd_problem_t *>(lp_problem);
1417 
1418  // The minimax problem is transformed into the LP notation
1419  // using the cost variable trick:
1420  //
1421  // Minimize c
1422  // Subject to:
1423  // c + sum_l t_kl + n_k >= 0 for negative cells n_k
1424  // c - sum_k t_kl + p_l >= 0 for positive cells p_l
1425 
1426  // Common LP mistakes during code development and their
1427  // CPLEX errors when running CPLEX in data checking mode:
1428  //
1429  // Error 1201 (column index ... out of range): Bad column
1430  // indexing, usually index_column out of bound for the
1431  // cost variables.
1432  //
1433  // Error 1222 (duplicate entry): Forgetting to increment
1434  // index_row, or index_column out of bound for the cost
1435  // variables.
1436 
1437  p->set_objective_sense(bpmpd_problem_t::minimize);
1438 
1439  // Rows (RHS of the constraints) of the LP problem
1440 
1441  static const size_t nsector_azimuth = 12;
1442 
1443  // Approximatively 2 pi / nsector_azimuth segmentation of
1444  // the CMS HCAL granularity
1445 
1446  static const size_t ncms_hcal_edge_pseudorapidity = 19 + 1;
1447  static const double cms_hcal_edge_pseudorapidity[
1448  ncms_hcal_edge_pseudorapidity] = {
1449  -5.191, -4.538, -4.013,
1450  -3.489, -2.853, -2.322, -1.830, -1.305, -0.783, -0.261,
1451  0.261, 0.783, 1.305, 1.830, 2.322, 2.853, 3.489,
1452  4.013, 4.538, 5.191
1453  };
1454 
1455  size_t nedge_pseudorapidity;
1456  const double *edge_pseudorapidity;
1457 
1458  nedge_pseudorapidity = ncms_hcal_edge_pseudorapidity;
1459  edge_pseudorapidity = cms_hcal_edge_pseudorapidity;
1460 
1461  const size_t nsuperblock = (nedge_pseudorapidity - 2) *
1462  nsector_azimuth;
1463 
1464  size_t index_row = 0;
1465  for (size_t index_pseudorapidity = 0;
1466  index_pseudorapidity < nedge_pseudorapidity - 2;
1467  index_pseudorapidity++) {
1468  for (size_t index_azimuth = 0;
1469  index_azimuth < nsector_azimuth - 1;
1470  index_azimuth++) {
1471  const size_t index_column =
1472  index_pseudorapidity * nsector_azimuth +
1473  index_azimuth;
1474  p->push_back_row(
1475  bpmpd_problem_t::greater_equal, 0);
1476  p->push_back_coefficient(
1477  index_row, index_column, 1);
1478  p->push_back_coefficient(
1479  index_row, nsuperblock + index_column, -1);
1480  index_row++;
1481  p->push_back_row(
1482  bpmpd_problem_t::greater_equal, 0);
1483  p->push_back_coefficient(
1484  index_row, index_column, 1);
1485  p->push_back_coefficient(
1486  index_row, nsuperblock + index_column + 1, -1);
1487  index_row++;
1488  p->push_back_row(
1489  bpmpd_problem_t::greater_equal, 0);
1490  p->push_back_coefficient(
1491  index_row, index_column, 1);
1492  p->push_back_coefficient(
1493  index_row,
1494  nsuperblock + index_column + nsector_azimuth, -1);
1495  index_row++;
1496  p->push_back_row(
1497  bpmpd_problem_t::greater_equal, 0);
1498  p->push_back_coefficient(
1499  index_row, index_column, 1);
1500  p->push_back_coefficient(
1501  index_row,
1502  nsuperblock + index_column + nsector_azimuth + 1,
1503  -1);
1504  index_row++;
1505  }
1506  const size_t index_column =
1507  index_pseudorapidity * nsector_azimuth +
1508  nsector_azimuth - 1;
1509  p->push_back_row(
1510  bpmpd_problem_t::greater_equal, 0);
1511  p->push_back_coefficient(
1512  index_row, index_column, 1);
1513  p->push_back_coefficient(
1514  index_row, nsuperblock + index_column, -1);
1515  index_row++;
1516  p->push_back_row(
1517  bpmpd_problem_t::greater_equal, 0);
1518  p->push_back_coefficient(
1519  index_row, index_column, 1);
1520  p->push_back_coefficient(
1521  index_row,
1522  nsuperblock + index_column - (nsector_azimuth - 1),
1523  -1);
1524  index_row++;
1525  p->push_back_row(
1526  bpmpd_problem_t::greater_equal, 0);
1527  p->push_back_coefficient(
1528  index_row, index_column, 1);
1529  p->push_back_coefficient(
1530  index_row,
1531  nsuperblock + index_column + nsector_azimuth, -1);
1532  index_row++;
1533  p->push_back_row(
1534  bpmpd_problem_t::greater_equal, 0);
1535  p->push_back_coefficient(
1536  index_row, index_column, 1);
1537  p->push_back_coefficient(
1538  index_row,
1539  nsuperblock + index_column + nsector_azimuth -
1540  (nsector_azimuth - 1),
1541  -1);
1542  index_row++;
1543  }
1544 
1545  const size_t nstaggered_block =
1546  (nedge_pseudorapidity - 1) * nsector_azimuth;
1547  const size_t nblock = nsuperblock + 2 * nstaggered_block;
1548 
1549  _nblock_subtract = std::vector<size_t>(_event.size(), 0);
1550 
1551  std::vector<size_t>
1552  positive_index(_event.size(), _event.size());
1553  size_t positive_count = 0;
1554 
1555  for (std::vector<particle_t>::const_iterator iterator =
1556  _event.begin();
1557  iterator != _event.end(); iterator++) {
1558  if (iterator->momentum_perp_subtracted >= 0) {
1559  positive_index[iterator - _event.begin()] =
1560  positive_count;
1561  positive_count++;
1562  }
1563  }
1564 
1565  _ncost = nblock + positive_count;
1566 
1567  const double sum_unequalized_0 = _equalization_threshold.first;
1568  const double sum_unequalized_1 = (2.0 / 3.0) * _equalization_threshold.first + (1.0 / 3.0) * _equalization_threshold.second;
1569  const double sum_unequalized_2 = (1.0 / 3.0) * _equalization_threshold.first + (2.0 / 3.0) * _equalization_threshold.second;
1570  const double sum_unequalized_3 = _equalization_threshold.second;
1571 
1572  std::vector<particle_t>::const_iterator
1573  iterator_particle = _event.begin();
1574  std::vector<bool>::const_iterator iterator_active =
1575  _active.begin();
1576  std::vector<std::vector<size_t> >::const_iterator
1577  iterator_recombine_index_outer =
1578  _recombine_index.begin();
1579  std::vector<std::vector<size_t> >::const_iterator
1580  iterator_recombine_unsigned_outer =
1581  _recombine_unsigned.begin();
1582  size_t index_column_max = _ncost - 1;
1583  for (; iterator_particle != _event.end();
1584  iterator_particle++, iterator_active++,
1585  iterator_recombine_index_outer++,
1586  iterator_recombine_unsigned_outer++) {
1587  if (*iterator_active) {
1588  int index_pseudorapidity = -1;
1589 
1591  for (size_t i = 1; i < nedge_pseudorapidity; i++) {
1592  if (iterator_particle->momentum.Eta() >= edge_pseudorapidity[i - 1] &&
1593  iterator_particle->momentum.Eta() < edge_pseudorapidity[i]) {
1594  index_pseudorapidity = i - 1;
1595  }
1596  }
1597 
1598  const int index_azimuth = floor(
1599  (iterator_particle->momentum.Phi() + M_PI) *
1600  ((nsector_azimuth >> 1) / M_PI));
1601 
1602  if (index_pseudorapidity != -1) {
1603  // p_i - sum t - u = c_i
1604  // or: c_i + u + sum_t = p_i
1605  // n_i + sum t - u <= 0
1606  // or: u - sum_t >= n_i
1607 
1608  // Inequality RHS
1609  p->push_back_row(
1610  iterator_particle->momentum_perp_subtracted >= 0 ?
1612  bpmpd_problem_t::greater_equal,
1613  iterator_particle->momentum_perp_subtracted);
1614 
1615  // Energy transfer coefficients t_kl
1616  const double sign = iterator_particle->momentum_perp_subtracted >= 0 ? 1 : -1;
1617  const size_t index_column_block_subtract =
1618  nsuperblock +
1619  (nedge_pseudorapidity - 1) * nsector_azimuth +
1620  index_pseudorapidity * nsector_azimuth +
1621  index_azimuth;
1622 
1623  _nblock_subtract[iterator_particle - _event.begin()] =
1624  index_column_block_subtract;
1625 
1626  if (iterator_particle->momentum_perp_subtracted >= 0) {
1627  const size_t index_column_cost =
1628  nblock + positive_index[iterator_particle - _event.begin()];
1629 
1630  p->push_back_coefficient(
1631  index_row, index_column_cost, 1);
1632  index_column_max =
1633  std::max(index_column_max, index_column_cost);
1634  }
1635  p->push_back_coefficient(
1636  index_row, index_column_block_subtract, 1);
1637  index_column_max =
1638  std::max(index_column_max, index_column_block_subtract);
1639 
1640  for (std::vector<size_t>::const_iterator
1641  iterator_recombine_index_inner =
1642  iterator_recombine_index_outer->begin();
1643  iterator_recombine_index_inner !=
1644  iterator_recombine_index_outer->end();
1645  iterator_recombine_index_inner++) {
1646  const size_t index_column =
1647  *iterator_recombine_index_inner +
1648  _ncost;
1649 
1650  p->push_back_coefficient(
1651  index_row, index_column, sign);
1652  index_column_max =
1653  std::max(index_column_max, index_column);
1654  }
1655  index_row++;
1656 
1657  const size_t index_column_block =
1658  nsuperblock +
1659  index_pseudorapidity * nsector_azimuth +
1660  index_azimuth;
1661 
1662  // sum_R c_i - o_i >= -d
1663  // or: d + sum_R c_i >= o_i
1664  // sum_R c_i - o_i <= d
1665  // or: d - sum_R c_i >= -o_i
1666 
1667  double sum_unequalized;
1668 
1669  sum_unequalized = 0;
1670  for (std::vector<size_t>::const_iterator
1671  iterator_recombine_unsigned_inner =
1672  iterator_recombine_unsigned_outer->begin();
1673  iterator_recombine_unsigned_inner !=
1674  iterator_recombine_unsigned_outer->end();
1675  iterator_recombine_unsigned_inner++) {
1676  sum_unequalized +=
1677  _event[*iterator_recombine_unsigned_inner].momentum_perp_subtracted;
1678  }
1679  sum_unequalized = std::max(0.0, sum_unequalized);
1680 
1681  if (sum_unequalized >= sum_unequalized_3 ||
1682  (sum_unequalized >= sum_unequalized_2 &&
1683  (iterator_particle - _event.begin()) % 2 == 0) ||
1684  (sum_unequalized >= sum_unequalized_1 &&
1685  (iterator_particle - _event.begin()) % 4 == 0) ||
1686  (sum_unequalized >= sum_unequalized_0 &&
1687  (iterator_particle - _event.begin()) % 8 == 0)) {
1688 
1689  const double weight = sum_unequalized *
1690  std::min(1.0, std::max(1e-3,
1691  iterator_particle->area));
1692 
1693  if (weight > 0) {
1694  p->push_back_row(
1695  bpmpd_problem_t::greater_equal,
1696  sum_unequalized);
1697 
1698  p->push_back_coefficient(
1699  index_row, index_column_block, 1.0 / weight);
1700 
1701  for (std::vector<size_t>::const_iterator
1702  iterator_recombine_unsigned_inner =
1703  iterator_recombine_unsigned_outer->begin();
1704  iterator_recombine_unsigned_inner !=
1705  iterator_recombine_unsigned_outer->end();
1706  iterator_recombine_unsigned_inner++) {
1707  if (_event[*iterator_recombine_unsigned_inner].momentum_perp_subtracted >= 0) {
1708  const size_t index_column_cost =
1709  nblock +
1710  positive_index[*iterator_recombine_unsigned_inner];
1711 
1712  p->push_back_coefficient(
1713  index_row, index_column_cost, 1);
1714  index_column_max =
1715  std::max(index_column_max, index_column_cost);
1716  }
1717  }
1718  index_row++;
1719 
1720  p->push_back_row(
1721  bpmpd_problem_t::greater_equal,
1722  -sum_unequalized);
1723 
1724  p->push_back_coefficient(
1725  index_row, index_column_block, _positive_bound_scale / weight);
1726 
1727  for (std::vector<size_t>::const_iterator iterator_recombine_unsigned_inner = iterator_recombine_unsigned_outer->begin();
1728  iterator_recombine_unsigned_inner != iterator_recombine_unsigned_outer->end();
1729  iterator_recombine_unsigned_inner++) {
1730  if (_event[*iterator_recombine_unsigned_inner].momentum_perp_subtracted >= 0) {
1731  const size_t index_column_cost =
1732  nblock +
1733  positive_index[*iterator_recombine_unsigned_inner];
1734 
1735  p->push_back_coefficient(
1736  index_row, index_column_cost, -1);
1737  index_column_max =
1738  std::max(index_column_max, index_column_cost);
1739  }
1740  }
1741  index_row++;
1742  }
1743 
1744  }
1745 
1746  }
1747  }
1748  }
1749 
1750  // Epsilon that breaks the degeneracy, in the same units
1751  // as the pT of the event (i.e. GeV)
1752  static const double epsilon_degeneracy = 1e-2;
1753 
1754  // Columns (variables and the objective coefficients) of
1755  // the LP problem
1756  //
1757  // Cost variables (objective coefficient 1)
1758  for (size_t i = 0; i < nsuperblock; i++) {
1759  p->push_back_column(
1761  }
1762  for (size_t i = nsuperblock; i < nsuperblock + nstaggered_block; i++) {
1763  p->push_back_column(
1765  }
1766  for (size_t i = nsuperblock + nstaggered_block; i < nsuperblock + 2 * nstaggered_block; i++) {
1767  p->push_back_column(
1769  }
1770  for (size_t i = nsuperblock + 2 * nstaggered_block; i < _ncost; i++) {
1771  p->push_back_column(
1773  }
1774  //fprintf(stderr, "%s:%d: %lu %lu\n", __FILE__, __LINE__, index_column_max, recombine_tie.size());
1775  // Energy transfer coefficients t_kl (objective
1776  // coefficient 0 + epsilon)
1777  for (size_t i = _ncost; i <= index_column_max; i++) {
1778  p->push_back_column(
1779  epsilon_degeneracy * _recombine_tie[i - _ncost],
1781  }
1782  }
1784  {
1785  bpmpd_problem_t lp_problem = reinterpret_cast<bpmpd_environment_t *>(_lp_environment)->problem();
1786 
1787  recombine_link();
1788  lp_populate(&lp_problem);
1789  lp_problem.optimize();
1790 
1791  int solution_status;
1792  double objective_value;
1793  std::vector<double> x;
1794  std::vector<double> pi;
1795 
1796  lp_problem.solve(solution_status, objective_value,
1797  x, pi);
1798 
1799  for (size_t k = _ncost; k < x.size(); k++) {
1800  if (_event[_recombine[k - _ncost].first].
1801  momentum_perp_subtracted < 0 &&
1802  _event[_recombine[k - _ncost].second].
1803  momentum_perp_subtracted >= 0 && x[k] >= 0) {
1804  _event[_recombine[k - _ncost].first].
1805  momentum_perp_subtracted += x[k];
1806  _event[_recombine[k - _ncost].second].
1807  momentum_perp_subtracted -= x[k];
1808  }
1809  }
1810  for (size_t k = 0; k < _event.size(); k++) {
1811  if (_nblock_subtract[k] != 0 &&
1812  x[_nblock_subtract[k]] >= 0) {
1813  _event[k].momentum_perp_subtracted -=
1814  x[_nblock_subtract[k]];
1815  }
1816  }
1817  }
1819  {
1820  for (std::vector<particle_t>::iterator iterator =
1821  _event.begin();
1822  iterator != _event.end(); iterator++) {
1823  iterator->momentum_perp_subtracted = std::max(
1824  0.0, iterator->momentum_perp_subtracted);
1825  }
1826  }
1828  {
1829  if (!_subtracted) {
1830  event_fourier();
1831  feature_extract();
1832  voronoi_area_incident();
1833  subtract_momentum();
1834  if (_remove_nonpositive) {
1835  equalize();
1836  remove_nonpositive();
1837  }
1838  _subtracted = true;
1839  }
1840  }
1841 
1843  const UECalibration *ue_,
1844  const double dr_max,
1845  const std::pair<double, double> equalization_threshold,
1846  const bool remove_nonpositive)
1847  : _remove_nonpositive(remove_nonpositive),
1848  _equalization_threshold(equalization_threshold),
1849  _radial_distance_square_max(dr_max * dr_max),
1850  _positive_bound_scale(0.2),
1851  _subtracted(false),
1852  ue(ue_)
1853  {
1855 
1856  static const size_t nedge_pseudorapidity = 15 + 1;
1857  static const double edge_pseudorapidity[nedge_pseudorapidity] = {
1858  -5.191, -2.650, -2.043, -1.740, -1.479, -1.131, -0.783, -0.522, 0.522, 0.783, 1.131, 1.479, 1.740, 2.043, 2.650, 5.191
1859  };
1860 
1861  _edge_pseudorapidity = std::vector<double>(
1862  edge_pseudorapidity,
1863  edge_pseudorapidity + nedge_pseudorapidity);
1864  allocate();
1865  }
1866 
1868  {
1869  deallocate();
1870  }
1871 
1882  const double perp, const double pseudorapidity,
1883  const double azimuth,
1884  const unsigned int reduced_particle_flow_id)
1885  {
1886  math::PtEtaPhiELorentzVector p(perp, pseudorapidity, azimuth, NAN);
1887 
1888  p.SetE(p.P());
1889  _event.push_back(particle_t(p, reduced_particle_flow_id));
1890  }
1895  {
1896  _event.clear();
1897  _subtracted = false;
1898  }
1905  {
1907 
1908  std::vector<double> ret;
1909 
1910  for (std::vector<particle_t>::const_iterator iterator =
1911  _event.begin();
1912  iterator != _event.end(); iterator++) {
1913  ret.push_back(iterator->momentum_perp_subtracted);
1914  }
1915 
1916  return ret;
1917  }
1919  {
1921 
1922  std::vector<double> ret;
1923 
1924  for (std::vector<particle_t>::const_iterator iterator =
1925  _event.begin();
1926  iterator != _event.end(); iterator++) {
1927  ret.push_back(iterator->momentum_perp_subtracted_unequalized);
1928  }
1929 
1930  return ret;
1931  }
1938  std::vector<double> VoronoiAlgorithm::particle_area(void)
1939  {
1941 
1942  std::vector<double> ret;
1943 
1944  for (std::vector<particle_t>::const_iterator iterator =
1945  _event.begin();
1946  iterator != _event.end(); iterator++) {
1947  ret.push_back(iterator->area);
1948  }
1949 
1950  return ret;
1951  }
1960  std::vector<std::set<size_t> > VoronoiAlgorithm::particle_incident(void)
1961  {
1963 
1964  std::vector<std::set<size_t> > ret;
1965 
1966  for (std::vector<particle_t>::const_iterator
1967  iterator_outer = _event.begin();
1968  iterator_outer != _event.end(); iterator_outer++) {
1969  std::set<size_t> e;
1970 
1971  for (std::set<std::vector<particle_t>::iterator>::
1972  const_iterator iterator_inner =
1973  iterator_outer->incident.begin();
1974  iterator_inner != iterator_outer->incident.begin();
1975  iterator_inner++) {
1976  e.insert(*iterator_inner - _event.begin());
1977  }
1978  ret.push_back(e);
1979  }
1980 
1981  return ret;
1982  }
1983  std::vector<double> VoronoiAlgorithm::perp_fourier(void)
1984  {
1986 
1987  return std::vector<double>(
1988  _perp_fourier->data(),
1989  _perp_fourier->data() +
1990  _perp_fourier->num_elements());
1991  }
1993  {
1994  return _edge_pseudorapidity.size();
1995  }
struct predc_s predc_
Definition: BitonicSort.h:8
struct toler_s toler_
double tfixvar
struct setden_s setden_
double dalpha
double center
std::vector< double > perp_fourier(void)
void subtract_momentum(void)
double ccorr
void event_fourier(void)
double target
double scfree
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
struct sprnod_s sprnod_
double corstp
CGAL::Voronoi_diagram_2< delaunay_triangulation_t, CGAL::Delaunay_triangulation_adaptation_traits_2< delaunay_triangulation_t >, CGAL::Delaunay_triangulation_caching_degeneracy_removal_policy_2< delaunay_triangulation_t > > voronoi_diagram_t
void remove_nonpositive(void)
#define NULL
Definition: scimark2.h:8
Definition: weight.py:1
std::vector< double > _edge_pseudorapidity
double tresy
void initialize_geometry(void)
double tplus
double supdens
struct numer_s numer_
#define constexpr
bool equal(const T &first, const T &second)
Definition: Equal.h:34
double upmax
double rhsnor
const Double_t pi
int solver_(double *obj, double *rhs, double *lbound, double *ubound, double *diag, double *odiag, double *xs, double *dxs, double *dxsn, double *up, double *dspr, double *ddspr, double *ddsprn, double *dsup, double *ddsup, double *ddsupn, double *dv, double *ddv, double *ddvn, double *prinf, double *upinf, double *duinf, double *scale, double *nonzeros, int *vartyp, int *slktyp, int *colpnt, int *ecolpnt, int *count, int *vcstat, int *pivots, int *invprm, int *snhead, int *nodtyp, int *inta1, int *prehis, int *rowidx, int *rindex, int *code, double *opt, int *iter, int *corect, int *fixn, int *dropn, int *fnzmax, int *fnzmin, double *addobj, double *bigbou, double *big, int *ft)
U second(std::pair< T, U > const &p)
delaunay_triangulation_t::Point point_2d_t
std::vector< double > particle_area(void)
void lp_populate(void *lp_problem)
void subtract_if_necessary(void)
double prmin
void push_back_particle(const double perp, const double pseudorapidity, const double azimuth, const unsigned int reduced_particle_flow_id)
struct compl_s compl_
struct initv_s initv_
struct itref_s itref_
#define BPMPD_VERSION_STRING
T sqrt(T t)
Definition: SSEVec.h:18
void clear(CLHEP::HepGenMatrix &m)
Helper function: Reset all elements of a matrix to 0.
Definition: matutil.cc:167
std::vector< std::set< size_t > > particle_incident(void)
double tsmall
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
const double infinity
double climit
struct param_s param_
Definition: value.py:1
T min(T a, T b)
Definition: MathUtil.h:58
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
Definition: HCMethods.h:49
double tfixslack
double varadd
double palpha
double objnor
#define M_PI
int k[5][pyjets_maxn]
double tlarge
boost::multi_array< double, 4 > * _perp_fourier
PtEtaPhiELorentzVectorD PtEtaPhiELorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:27
double slkadd
double dumin
void feature_extract(void)
struct mscal_s mscal_
VoronoiAlgorithm(const UECalibration *ue, const double dr_max, const std::pair< double, double > equalization_threshold=std::pair< double, double >(5.0, 35.0), const bool remove_nonpositive=true)
T perp() const
Magnitude of transverse component.
void voronoi_area_incident(void)
#define begin
Definition: vmac.h:30
Definition: big.h:8
size_t nedge_pseudorapidity(void) const
struct drop_s drop_
double tresx
double scdiff
struct dims_s dims_
CGAL::Polygon_2< CGAL::Exact_predicates_inexact_constructions_kernel > polygon_t
std::vector< double > subtracted_unequalized_perp(void)
struct predp_s predp_
struct ascal_s ascal_
double slklim
struct factor_s factor_
save
Definition: cuy.py:1163
std::vector< double > subtracted_equalized_perp(void)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
T normalizedPhi(T phi)
Definition: normalizedPhi.h:9
#define BPMPD_INFINITY_BOUND