bpp-core3  3.0.0
ContingencyTableGenerator.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include <iostream>
6 
7 #include "../VectorTools.h"
9 
10 using namespace bpp;
11 using namespace std;
12 
13 /**************************************************************************/
14 
16  const std::vector<size_t>& nrowt,
17  const std::vector<size_t>& ncolt) :
18  nrowt_(nrowt),
19  ncolt_(ncolt),
20  nrow_(nrowt.size()),
21  ncol_(ncolt.size()),
22  nrowm_(0),
23  ncolm_(0),
24  jwork_(ncolt.size()),
25  ntot_(0),
26  fact_(0)
27 {
28  if (nrow_ < 2 || ncol_ < 2)
29  throw Exception("ContingencyTableGenerator. Input marginals must have size greater than 1.");
32  throw Exception("ContingencyTableGenerator. Marginal do not sum to the same value.");
33  nrowm_ = nrow_ - 1;
34  ncolm_ = ncol_ - 1;
35  fact_.resize(ntot_ + 1);
36  double x = 0.;
37  fact_[0] = 0.;
38  for (size_t i = 1; i <= ntot_; ++i)
39  {
40  x = x + log(static_cast<double>(i));
41  fact_[i] = x;
42  }
43 }
44 
45 /* Algorithm AS 159 Applied Statistics (1981), vol. 30, no. 1
46  original (C) Royal Statistical Society 1981
47 
48  Generate random two-way table with given marginal totals.
49 
50  Heavily pretty edited by Martin Maechler, Dec 2003
51  use double precision for integer multiplication (against overflow);
52 
53  Taken from R source file rcont.c and adapted by Julien Dutheil, Dec 2010
54  */
56 {
57  RowMatrix<size_t> table(nrow_, ncol_); // Result
58  size_t j, l, m, ia, ib, ic, jc, id, ie, ii, nll, nlm, nr_1, nc_1;
59  long double x, y, dummy, sumprb;
60  bool lsm, lsp;
61 
62  nr_1 = nrow_ - 1;
63  nc_1 = ncol_ - 1;
64 
65  ib = 0; /* -Wall */
66 
67  /* Construct random matrix */
68  for (j = 0; j < nc_1; ++j)
69  {
70  jwork_[j] = ncolt_[j];
71  }
72 
73  jc = ntot_;
74 
75  for (l = 0; l < nr_1; ++l) /* ----- matrix[ l, * ] ----- */
76  {
77  ia = nrowt_[l];
78  ic = jc;
79  jc -= ia; /* = n_tot - sum(nr[0:l]) */
80 
81  for (m = 0; m < nc_1; ++m)
82  {
83  id = jwork_[m];
84  ie = ic;
85  ic -= id;
86  ib = ie - ia;
87  ii = ib - id;
88 
89  if (ie == 0) /* Row [l,] is full, fill rest with zero entries */
90  {
91  for (j = m; j < nc_1; ++j)
92  {
93  table(l, j) = 0;
94  }
95  ia = 0;
96  break;
97  }
98 
99  /* Generate pseudo-random number */
101 
102  do /* Outer Loop */
103 
104  /* Compute conditional expected value of MATRIX(L, M) */
105 
106  {
107  nlm = ia * static_cast<size_t>((static_cast<long double>(id) / static_cast<long double>(ie)) + 0.5);
108  x = exp(fact_[ia] + fact_[ib] + fact_[ic] + fact_[id]
109  - fact_[ie] - fact_[nlm]
110  - fact_[id - nlm] - fact_[ia - nlm] - fact_[ii + nlm]);
111  if (x >= dummy)
112  break;
113 
114  sumprb = x;
115  y = x;
116  nll = nlm;
117 
118  do
119  {
120  /* Increment entry in row L, column M */
121  j = (id - nlm) * (ia - nlm);
122  lsp = (j == 0);
123  if (!lsp)
124  {
125  ++nlm;
126  x = x * static_cast<long double>(j) / (static_cast<long double>(nlm) * static_cast<long double>(ii + nlm));
127  sumprb += x;
128  if (sumprb >= dummy)
129  goto L160;
130  }
131 
132  do
133  {
134  /* Decrement entry in row L, column M */
135  j = nll * (ii + nll);
136  lsm = (j == 0);
137  if (!lsm)
138  {
139  --nll;
140  y = y * static_cast<long double>(j) / (static_cast<long double>(id - nll) * static_cast<long double>(ia - nll));
141  sumprb += y;
142  if (sumprb >= dummy)
143  {
144  nlm = nll;
145  goto L160;
146  }
147  /* else */
148  if (!lsp)
149  break; /* to while (!lsp) */
150  }
151  }
152  while (!lsm);
153  }
154  while (!lsp);
155 
157  }
158  while (true);
159 
160 L160:
161  table(l, m) = nlm;
162  ia -= nlm;
163  jwork_[m] -= nlm;
164  }
165  table(l, nc_1) = ia; /* last column in row l */
166  }
167 
168  /* Compute entries in last row of MATRIX */
169  for (m = 0; m < nc_1; ++m)
170  {
171  table(nr_1, m) = jwork_[m];
172  }
173 
174  table(nr_1, nc_1) = ib - table(nr_1, nc_1 - 1);
175 
176  return table;
177 }
178 
179 /**************************************************************************/
static T sum(const std::vector< T > &v1)
Definition: VectorTools.h:587
STL namespace.
Matrix storage by row.
Definition: Matrix.h:92
static double giveRandomNumberBetweenZeroAndEntry(double entry)
Get a double random value (between 0 and specified range).
Definition: RandomTools.h:78
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
ContingencyTableGenerator(const std::vector< size_t > &nrowt, const std::vector< size_t > &ncolt)