bpp-core  2.2.0
ContingencyTableGenerator.cpp
Go to the documentation of this file.
1 //
2 // File ContingencyTableGenerator.cpp
3 // Author: Julien Dutheil
4 // Created on: Fri Dec 10 2010 16:19
5 //
6 
7 
8 /*
9 Copyright or © or Copr. CNRS, (November 17, 2004)
10 
11 This software is a computer program whose purpose is to provide classes
12 for numerical calculus.
13 
14 This software is governed by the CeCILL license under French law and
15 abiding by the rules of distribution of free software. You can use,
16 modify and/ or redistribute the software under the terms of the CeCILL
17 license as circulated by CEA, CNRS and INRIA at the following URL
18 "http://www.cecill.info".
19 
20 As a counterpart to the access to the source code and rights to copy,
21 modify and redistribute granted by the license, users are provided only
22 with a limited warranty and the software's author, the holder of the
23 economic rights, and the successive licensors have only limited
24 liability.
25 
26 In this respect, the user's attention is drawn to the risks associated
27 with loading, using, modifying and/or developing or reproducing the
28 software by the user in light of its specific status of free software,
29 that may mean that it is complicated to manipulate, and that also
30 therefore means that it is reserved for developers and experienced
31 professionals having in-depth computer knowledge. Users are therefore
32 encouraged to load and test the software's suitability as regards their
33 requirements in conditions enabling the security of their systems and/or
34 data to be ensured and, more generally, to use and operate it in the
35 same conditions as regards security.
36 
37 The fact that you are presently reading this means that you have had
38 knowledge of the CeCILL license and that you accept its terms.
39 */
40 
42 #include "../VectorTools.h"
43 
44 #include <iostream>
45 
46 using namespace bpp;
47 using namespace std;
48 
49 /**************************************************************************/
50 
52  const std::vector<size_t>& nrowt,
53  const std::vector<size_t>& ncolt):
54  nrowt_(nrowt),
55  ncolt_(ncolt),
56  nrow_(nrowt.size()),
57  ncol_(ncolt.size()),
58  nrowm_(0),
59  ncolm_(0),
60  jwork_(ncolt.size()),
61  ntot_(0),
62  fact_(0)
63 {
64  if (nrow_ < 2 || ncol_ < 2)
65  throw Exception("ContingencyTableGenerator. Input marginals must have size greater than 1.");
68  throw Exception("ContingencyTableGenerator. Marginal do not sum to the same value.");
69  nrowm_ = nrow_ - 1;
70  ncolm_ = ncol_ - 1;
71  fact_.resize(ntot_ + 1);
72  double x = 0.;
73  fact_[0] = 0.;
74  for (unsigned int i = 1; i <= ntot_; i++) {
75  x = x + log(static_cast<double>(i));
76  fact_[i] = x;
77  }
78 }
79 
80 /* Algorithm AS 159 Applied Statistics (1981), vol. 30, no. 1
81  original (C) Royal Statistical Society 1981
82 
83  Generate random two-way table with given marginal totals.
84 
85  Heavily pretty edited by Martin Maechler, Dec 2003
86  use double precision for integer multiplication (against overflow);
87 
88  Taken from R source file rcont.c and adapted by Julien Dutheil, Dec 2010
89 */
90 
92 {
93  RowMatrix<size_t> table(nrow_, ncol_); //Result
94  size_t j, l, m, ia, ib, ic, jc, id, ie, ii, nll, nlm, nr_1, nc_1;
95  long double x, y, dummy, sumprb;
96  bool lsm, lsp;
97 
98  nr_1 = nrow_ - 1;
99  nc_1 = ncol_ - 1;
100 
101  ib = 0; /* -Wall */
102 
103  /* Construct random matrix */
104  for (j = 0; j < nc_1; ++j)
105  jwork_[j] = ncolt_[j];
106 
107  jc = ntot_;
108 
109  for (l = 0; l < nr_1; ++l) { /* ----- matrix[ l, * ] ----- */
110  ia = nrowt_[l];
111  ic = jc;
112  jc -= ia;/* = n_tot - sum(nr[0:l]) */
113 
114  for (m = 0; m < nc_1; ++m) {
115  id = jwork_[m];
116  ie = ic;
117  ic -= id;
118  ib = ie - ia;
119  ii = ib - id;
120 
121  if (ie == 0) { /* Row [l,] is full, fill rest with zero entries */
122  for (j = m; j < nc_1; ++j)
123  table(l, j) = 0;
124  ia = 0;
125  break;
126  }
127 
128  /* Generate pseudo-random number */
129  dummy = generator.drawNumber();
130 
131  do {/* Outer Loop */
132 
133  /* Compute conditional expected value of MATRIX(L, M) */
134 
135  nlm = static_cast<size_t>(ia * (static_cast<long double>(id) / static_cast<long double>(ie)) + 0.5);
136  x = exp(fact_[ia] + fact_[ib] + fact_[ic] + fact_[id]
137  - fact_[ie] - fact_[nlm]
138  - fact_[id - nlm] - fact_[ia - nlm] - fact_[ii + nlm]);
139  if (x >= dummy)
140  break;
141 
142  sumprb = x;
143  y = x;
144  nll = nlm;
145 
146  do {
147  /* Increment entry in row L, column M */
148  j = static_cast<size_t>((id - nlm) * static_cast<long double>(ia - nlm));
149  lsp = (j == 0);
150  if (!lsp) {
151  ++nlm;
152  x = x * j / (static_cast<long double>(nlm) * (ii + nlm));
153  sumprb += x;
154  if (sumprb >= dummy)
155  goto L160;
156  }
157 
158  do {
159  /* Decrement entry in row L, column M */
160  j = nll * (ii + nll);
161  lsm = (j == 0);
162  if (!lsm) {
163  --nll;
164  y = y * j / (static_cast<long double>(id - nll) * (ia - nll));
165  sumprb += y;
166  if (sumprb >= dummy) {
167  nlm = nll;
168  goto L160;
169  }
170  /* else */
171  if (!lsp)
172  break;/* to while (!lsp) */
173  }
174  } while (!lsm);
175  } while (!lsp);
176 
177  dummy = sumprb * generator.drawNumber();
178 
179  } while (true);
180 
181 L160:
182  table(l, m) = nlm;
183  ia -= nlm;
184  jwork_[m] -= nlm;
185  }
186  table(l, nc_1) = ia;/* last column in row l */
187  }
188 
189  /* Compute entries in last row of MATRIX */
190  for (m = 0; m < nc_1; ++m)
191  table(nr_1, m) = jwork_[m];
192 
193  table(nr_1, nc_1) = ib - table(nr_1, nc_1 - 1);
194 
195  return table;
196 }
197 
198 /**************************************************************************/
199 
This class allows to perform a correspondence analysis.
static T sum(const std::vector< T > &v1)
Definition: VectorTools.h:614
STL namespace.
This is the interface for the Random Number Generators.
Definition: RandomFactory.h:52
Matrix storage by row.
Definition: Matrix.h:129
virtual double drawNumber() const =0
Return a random number.
RowMatrix< size_t > rcont2(const RandomFactory &generator= *RandomTools::DEFAULT_GENERATOR)
Exception base class.
Definition: Exceptions.h:57
ContingencyTableGenerator(const std::vector< size_t > &nrowt, const std::vector< size_t > &ncolt)