← Back to list

Paper Implementation : Sequential Monte Carlo Methods for Statistical Analysis of Tables

Implemented this in C and Julia, lol it took me 2 years to understand the paper — skill issue on my end

Kibicho Murage · 2024-12-20 08:53 · 0 claps · 8.4 min read
#markov-chains #monte-carlo-simulation #importance-sampling
Open on Medium ↗

Paper Implementation : Sequential Monte Carlo Methods for Statistical

Analysis of Tables

Implemented this in C and Julia, lol it took me 2 years to understand the paper — skill issue on my end

I implement the paper Sequential Monte Carlo Methods for Statistical Analysis of Tables by Yuguo Chen, Persi Diaconis, Susan P. Holmes, and Jun S.Liu

These are part of my startup notes —

  • Test using contingency table in Diaconis’ 1995 paper RECTANGULAR ARRAYS WITH FIXED MARGINS

5 | 2 | 3 | 10 50| 7| 5 |62 3 | 6 | 4 |13 5 | 3 | 3 | 11

2 | 7 |30| 39

Update — I changed to using libgmp, my accuracy issues were a consequence of integer overflow.

3rd Feb 2025 Update

I’m obsessed with this paper. I saw that only the row sums and column sums are needed. I changed the code (3rd entry with libgmp) to use less memory.

C implementation — rand() is less accurate than Julia’s mersenne twister

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <string.h> // For memcpy
#define MAX_ChenDiaconis(a, b) ((a) > (b) ? (a) : (b))
#define MIN_ChenDiaconis(a, b) ((a) < (b) ? (a) : (b))
#define MATRIX_INDEX(x, y, cols) ((x) * (cols) + (y))
int *GenerateRowSums(int height, int width, int *matrix)
{
 int *result = calloc(height, sizeof(int));
 for(int i = 0; i < height; i++)
 {
  int sum = 0;
  for(int j = 0; j < width; j++)
  {
   sum += matrix[(i*width) + j];
  }
  result[i]=sum;
 }
 return result;
}

int *GenerateColumnSums(int height, int width, int *matrix)
{
 int *result = calloc(width, sizeof(int));
 for(int j = 0; j < width; j++)
 {
  int sum = 0;
  for(int i = 0; i < height; i++)
  {
   sum += matrix[(i*width) + j];
  }
  result[j] = sum;
 }
 return result;
}

void PrintIntArray_ChenDiaconis(int length, int *array)
{
 for(int i = 0; i < length; i++)
 {
  printf("%3d, ", array[i]);
 }
 printf("\n");
}

int RandRange(int lowerBound, int upperBound)
{
    return lowerBound + rand() % (upperBound - lowerBound + 1);
}

int MakeDecision(int currentColumnSum, int currentRowSum, int currentTotalSum, int *currentQ)
{
 int decision = 0;
 int lowerBound = MAX_ChenDiaconis(0, currentColumnSum + currentRowSum - currentTotalSum);
 int upperBound = MIN_ChenDiaconis(currentColumnSum, currentRowSum);
 decision = RandRange(lowerBound, upperBound);
 *currentQ = upperBound - lowerBound + 1;
 return decision;
}

void PrintTable_ChenDiaconis(int numberOfRows, int numberOfColumns, int *table)
{
 for(int i = 0; i < numberOfRows; i++)
 {
  for(int j = 0; j < numberOfColumns; j++)
  {
   printf("%3d, ", table[MATRIX_INDEX(i,j,numberOfColumns)]);
  }
  printf("\n");
 }
}

int GenerateTable(int numberOfTables, int numberOfRows, int numberOfColumns, int tableIndex, int totalSum, int *rowSums, int *columnSums, int **tableHolder)
{
 assert(tableIndex > -1);
 assert(tableIndex < numberOfTables-1);
 long currentQ = 1; //maybe change to mpz_t
 int currentColumnSum = 0;
 int currentRowSum = 0;
 int currentTotalSum = 0;
 int currentTableValue = 0;
 int decision = 0;
 int qHolder = 0;
 for(int i = 0; i < numberOfColumns; i++)
 {
  currentColumnSum = columnSums[i];
  currentTotalSum = totalSum;
  for(int j = 0; j < numberOfRows; j++)
  {
   currentTableValue = tableHolder[tableIndex][MATRIX_INDEX(j,i,numberOfColumns)];
   currentRowSum = rowSums[j];
   decision = MakeDecision(currentColumnSum, currentRowSum, currentTotalSum, &qHolder);
   currentQ *= qHolder;
   tableHolder[tableIndex+1][MATRIX_INDEX(j,i,numberOfColumns)] = decision; 


   currentColumnSum -= decision;
   currentTotalSum -= currentRowSum;
   rowSums[j] -= decision;
   totalSum -= decision;

  }
 }
 return currentQ;
}
int main()
{
 srand(55455);
 int numberOfTables = 1000000;
 int numberOfRows = 5;
 int numberOfColumns = 3;
 long qT = 0;
 int **tableHolder = malloc(numberOfTables * sizeof(int*));for(int i = 0; i < numberOfTables; i++){tableHolder[i] = calloc(numberOfRows * numberOfColumns, sizeof(int));}

 tableHolder[0][MATRIX_INDEX(0,0,numberOfColumns)] = 5; tableHolder[0][MATRIX_INDEX(0,1,numberOfColumns)] = 2;tableHolder[0][MATRIX_INDEX(0,2,numberOfColumns)] = 3;
 tableHolder[0][MATRIX_INDEX(1,0,numberOfColumns)] = 50;tableHolder[0][MATRIX_INDEX(1,1,numberOfColumns)] = 7;tableHolder[0][MATRIX_INDEX(1,2,numberOfColumns)] = 5;
 tableHolder[0][MATRIX_INDEX(2,0,numberOfColumns)] = 3; tableHolder[0][MATRIX_INDEX(2,1,numberOfColumns)] = 6;tableHolder[0][MATRIX_INDEX(2,2,numberOfColumns)] = 4;
 tableHolder[0][MATRIX_INDEX(3,0,numberOfColumns)] = 5; tableHolder[0][MATRIX_INDEX(3,1,numberOfColumns)] = 3;tableHolder[0][MATRIX_INDEX(3,2,numberOfColumns)] = 3;
 tableHolder[0][MATRIX_INDEX(4,0,numberOfColumns)] = 2; tableHolder[0][MATRIX_INDEX(4,1,numberOfColumns)] = 7;tableHolder[0][MATRIX_INDEX(4,2,numberOfColumns)] = 30;
 int *rowSums = GenerateRowSums(numberOfRows, numberOfColumns, tableHolder[0]);
 int *columnSums = GenerateColumnSums(numberOfRows, numberOfColumns, tableHolder[0]);

 int *rowSumsCopy = GenerateRowSums(numberOfRows, numberOfColumns, tableHolder[0]);
 int *columnSumsCopy = GenerateColumnSums(numberOfRows, numberOfColumns, tableHolder[0]);

 int totalSum = 0; for(int i = 0; i < numberOfRows; i++){totalSum += rowSums[i];} 
 //PrintIntArray_ChenDiaconis(numberOfRows, rowSums);PrintIntArray_ChenDiaconis(numberOfColumns, columnSums);printf("%3d\n", totalSum);


 for(int tableIndex = 0; tableIndex < numberOfTables-1; tableIndex++)
 {
  memcpy(rowSumsCopy, rowSums, numberOfRows * sizeof(int));
  memcpy(columnSumsCopy, columnSums, numberOfColumns * sizeof(int));
  qT += GenerateTable(numberOfTables, numberOfRows, numberOfColumns, tableIndex, totalSum, rowSumsCopy, columnSumsCopy, tableHolder);
  //PrintTable_ChenDiaconis(numberOfRows, numberOfColumns, tableHolder[tableIndex+1]);printf("\n");
 }
 printf("Approximate Count : %3ld : %d\n", qT / numberOfTables, 238243776);


 free(rowSums);free(columnSums);free(rowSumsCopy);free(columnSumsCopy);
 for(int i = 0; i < numberOfTables; i++){free(tableHolder[i]);}free(tableHolder);
 return 0;
}

Julia — accurate because of Mersenne Twister

using Random
using HypothesisTests
using Dates

myGlobalProgramRNG = MersenneTwister(123) 

function FindRowSums(table, tableIndex)
 for i in 1:numberOfRows-1
  rowSum = 0
  for j in 1:numberOfColumns-1
   rowSum += table[i, j ,tableIndex]
  end
  table[i, numberOfColumns ,tableIndex] = rowSum
 end
end

function FindColumnSums(table, tableIndex)
 for i in 1:numberOfColumns
  columnSum = 0
  for j in 1:numberOfRows-1
   columnSum += table[j,i,tableIndex]
  end
  table[numberOfRows,i,tableIndex] = columnSum
 end
end

function MakeDecision(c1,r1,M)
 #lowerBound = max(0, c1+r1-M)
 lowerBound = max(0, c1+r1-M) 
 upperBound = min(r1,c1) 
 #println("Lower: ", lowerBound, " Upper: ", upperBound)
 result = rand(myGlobalProgramRNG,lowerBound:upperBound)
 currentQ = ((upperBound - lowerBound) + 1)
 return (result, currentQ)
end

function GenerateTable(table, tableIndex)
 currentQ  = 1
 for i in 1:numberOfColumns-1
  c1 = table[numberOfRows,i,tableIndex] #Column sum
  M  = table[numberOfRows,numberOfColumns,tableIndex]
  for j in 1:numberOfRows-1
   a = table[j,i,tableIndex] 
   r1 = table[j,numberOfColumns,tableIndex]
   #println(c1," ", r1," ",M)
    decisionResult = MakeDecision(c1,r1,M)
   a11 = decisionResult[1]
   currentQ *= decisionResult[2]
   c1 -= a11
   M  -= r1 
   table[j,i,tableIndex+1] = a11
   table[j,numberOfColumns,tableIndex] -= a11
   table[numberOfRows,numberOfColumns,tableIndex] -= a11
  end
 end
 return currentQ
end

function FindMarginalSums(table, tableIndex)
 FindRowSums(table,tableIndex)
 FindColumnSums(table,tableIndex)
end

function GenerateTables(table, numberOfTables)
    t1 = now()
 qT = 0
 for i in 1 : numberOfTables-1
  FindMarginalSums(table,i)
  qt = GenerateTable(table,i) #returns an integer
  FindMarginalSums(table,i)
  qT += qt
  qTArray[i] = qt
 end
 FindMarginalSums(table,numberOfTables)
    t2 =now() + Hour(1)
 println("Approximate Total: ", qT/numberOfTables)
    println("Time", t2 - t1)
end

function Indicator(originalChiStatistic, chiSquareStatistic)
 if(chiSquareStatistic <= originalChiStatistic)
  return 1
 else
  return 0
 end
end
function CalculateMu(table, expectedTable, numberOfTables)
 #degreesOfFreedom = (numberOfRows - 2) * (numberOfColumns - 2)
 originalChiStatistic = 0;

 muNumerator = 0
 muDenominator = 0
 z = 0
 for i in 1 : numberOfTables-1
  chiSquareStatistic = 0
  for j in 1 : numberOfRows-1
   for k in 1 : numberOfColumns-1
    expectedValue = convert(Float64, table[j, numberOfColumns,i]) * convert(Float64, table[numberOfRows, k,i]) / convert(Float64, table[numberOfRows, numberOfColumns,i]) 
    expectedValue = (convert(Float64, table[j, k,i]) - expectedValue)^2 / expectedValue
    chiSquareStatistic += expectedValue
   end
  end
  if i == 1
   originalChiStatistic = chiSquareStatistic
   println(originalChiStatistic)
  end

  if i == 2
   println(chiSquareStatistic)
  end

  fT = Indicator(originalChiStatistic, chiSquareStatistic)
  muNumerator += convert(Float64, fT * (1 / qTArray[i]))
  muDenominator += convert(Float64, (1 / qTArray[i]))
  #z += fT
  #println(chiSquareStatistic, " ", fT," ", qTArray[i])
 end
 mu = muNumerator / muDenominator

 println("Mu value: ", mu, " ") 
end

numberOfTables = 100000
numberOfRows = 6 #6
numberOfColumns = 4 #4
table = zeros(Int64, (numberOfRows,numberOfColumns,numberOfTables))
expectedTable = zeros(Float64, (numberOfRows-1,numberOfColumns-1,numberOfTables))
qTArray = zeros(Int64,numberOfTables, 1)

table[1,1,1] =  5; table[1,2,1] = 2; table[1,3,1] = 3;
table[2,1,1] = 50; table[2,2,1] = 7; table[2,3,1] = 5;
table[3,1,1] =  3; table[3,2,1] = 6; table[3,3,1] = 4;
table[4,1,1] =  5; table[4,2,1] = 3; table[4,3,1] = 3;
table[5,1,1] =  2; table[5,2,1] = 7; table[5,3,1] =30;
#Perhaps try
#table[1,1,1] =  5; table[1,2,1] = 2; table[1,3,1] = 3;
#table[2,1,1] = 50; table[2,2,1] = 7; table[2,3,1] = 5;

GenerateTables(table, numberOfTables)
CalculateMu(table, expectedTable, numberOfTables)

libgmp implementation in C, super accurate

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gmp.h>
#include <assert.h>
#include <string.h> // For memcpy
#define MAX_ChenDiaconis(a, b) ((a) > (b) ? (a) : (b))
#define MIN_ChenDiaconis(a, b) ((a) < (b) ? (a) : (b))
#define MATRIX_INDEX(x, y, cols) ((x) * (cols) + (y))

int *GenerateRowSums(int height, int width, int *matrix)
{
 int *result = calloc(height, sizeof(int));
 for(int i = 0; i < height; i++)
 {
  int sum = 0;
  for(int j = 0; j < width; j++)
  {
   sum += matrix[(i*width) + j];
  }
  result[i]=sum;
 }
 return result;
}

int *GenerateColumnSums(int height, int width, int *matrix)
{
 int *result = calloc(width, sizeof(int));
 for(int j = 0; j < width; j++)
 {
  int sum = 0;
  for(int i = 0; i < height; i++)
  {
   sum += matrix[(i*width) + j];
  }
  result[j] = sum;
 }
 return result;
}

void PrintIntArray_ChenDiaconis(int length, int *array)
{
 for(int i = 0; i < length; i++)
 {
  printf("%3d, ", array[i]);
 }
 printf("\n");
}

int RandRange(int lowerBound, int upperBound)
{
    return lowerBound + rand() % (upperBound - lowerBound + 1);
}

int MakeDecision(int currentColumnSum, int currentRowSum, int currentTotalSum, int *currentQ)
{
 int decision = 0;
 int lowerBound = MAX_ChenDiaconis(0, currentColumnSum + currentRowSum - currentTotalSum);
 int upperBound = MIN_ChenDiaconis(currentColumnSum, currentRowSum);
 decision = RandRange(lowerBound, upperBound);
 *currentQ = upperBound - lowerBound + 1;
 return decision;
}

void PrintTable_ChenDiaconis(int numberOfRows, int numberOfColumns, int *table)
{
 for(int i = 0; i < numberOfRows; i++)
 {
  for(int j = 0; j < numberOfColumns; j++)
  {
   printf("%3d, ", table[MATRIX_INDEX(i,j,numberOfColumns)]);
  }
  printf("\n");
 }
}

void GenerateTable(int numberOfTables, int numberOfRows, int numberOfColumns, int tableIndex, int totalSum, int *rowSums, int *columnSums, int **tableHolder, mpz_t qT)
{
 assert(tableIndex > -1);
 assert(tableIndex < numberOfTables-1);
 mpz_t currentQ; mpz_init(currentQ);mpz_set_ui(currentQ, 1);
 int currentColumnSum = 0;
 int currentRowSum = 0;
 int currentTotalSum = 0;
 int currentTableValue = 0;
 int decision = 0;
 int qHolder = 0;
 for(int i = 0; i < numberOfColumns; i++)
 {
  currentColumnSum = columnSums[i];
  currentTotalSum = totalSum;
  for(int j = 0; j < numberOfRows; j++)
  {
   currentTableValue = tableHolder[tableIndex][MATRIX_INDEX(j,i,numberOfColumns)];
   currentRowSum = rowSums[j];
   decision = MakeDecision(currentColumnSum, currentRowSum, currentTotalSum, &qHolder);
   mpz_mul_ui(currentQ, currentQ, (unsigned long int) qHolder);
   tableHolder[tableIndex+1][MATRIX_INDEX(j,i,numberOfColumns)] = decision; 
   currentColumnSum -= decision;
   currentTotalSum -= currentRowSum;
   rowSums[j] -= decision;
   totalSum -= decision;
  }
 }
 mpz_add(qT, qT, currentQ);
 mpz_clear(currentQ);
}

int TestDiaconis()
{
 srand(55455);
 int numberOfTables = 10000;
 int numberOfRows = 5;
 int numberOfColumns = 3;
 mpz_t qT; mpz_init(qT);mpz_set_ui(qT, 0);
 int **tableHolder = malloc(numberOfTables * sizeof(int*));for(int i = 0; i < numberOfTables; i++){tableHolder[i] = calloc(numberOfRows * numberOfColumns, sizeof(int));}

 tableHolder[0][MATRIX_INDEX(0,0,numberOfColumns)] = 5; tableHolder[0][MATRIX_INDEX(0,1,numberOfColumns)] = 2;tableHolder[0][MATRIX_INDEX(0,2,numberOfColumns)] = 3;
 tableHolder[0][MATRIX_INDEX(1,0,numberOfColumns)] = 50;tableHolder[0][MATRIX_INDEX(1,1,numberOfColumns)] = 7;tableHolder[0][MATRIX_INDEX(1,2,numberOfColumns)] = 5;
 tableHolder[0][MATRIX_INDEX(2,0,numberOfColumns)] = 3; tableHolder[0][MATRIX_INDEX(2,1,numberOfColumns)] = 6;tableHolder[0][MATRIX_INDEX(2,2,numberOfColumns)] = 4;
 tableHolder[0][MATRIX_INDEX(3,0,numberOfColumns)] = 5; tableHolder[0][MATRIX_INDEX(3,1,numberOfColumns)] = 3;tableHolder[0][MATRIX_INDEX(3,2,numberOfColumns)] = 3;
 tableHolder[0][MATRIX_INDEX(4,0,numberOfColumns)] = 2; tableHolder[0][MATRIX_INDEX(4,1,numberOfColumns)] = 7;tableHolder[0][MATRIX_INDEX(4,2,numberOfColumns)] = 30;
 int *rowSums = GenerateRowSums(numberOfRows, numberOfColumns, tableHolder[0]);
 int *columnSums = GenerateColumnSums(numberOfRows, numberOfColumns, tableHolder[0]);

 int *rowSumsCopy = GenerateRowSums(numberOfRows, numberOfColumns, tableHolder[0]);
 int *columnSumsCopy = GenerateColumnSums(numberOfRows, numberOfColumns, tableHolder[0]);

 int totalSum = 0; for(int i = 0; i < numberOfRows; i++){totalSum += rowSums[i];} 
 //PrintIntArray_ChenDiaconis(numberOfRows, rowSums);PrintIntArray_ChenDiaconis(numberOfColumns, columnSums);printf("%3d\n", totalSum);


 for(int tableIndex = 0; tableIndex < numberOfTables-1; tableIndex++)
 {
  memcpy(rowSumsCopy, rowSums, numberOfRows * sizeof(int));
  memcpy(columnSumsCopy, columnSums, numberOfColumns * sizeof(int));
  GenerateTable(numberOfTables, numberOfRows, numberOfColumns, tableIndex, totalSum, rowSumsCopy, columnSumsCopy, tableHolder, qT);
  //PrintTable_ChenDiaconis(numberOfRows, numberOfColumns, tableHolder[tableIndex+1]);printf("\n");
 }
 mpz_div_ui(qT, qT, (unsigned long int) numberOfTables);
 gmp_printf("Approximate Count : %3Zd : %d\n", qT , 238243776);


 mpz_clear(qT);free(rowSums);free(columnSums);free(rowSumsCopy);free(columnSumsCopy);
 for(int i = 0; i < numberOfTables; i++){free(tableHolder[i]);}free(tableHolder);
 return 0;
}

3rd Feb 2025 update

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gmp.h>
#include <assert.h>
#include <string.h> // For memcpy
#define MAX_ChenDiaconis(a, b) ((a) > (b) ? (a) : (b))
#define MIN_ChenDiaconis(a, b) ((a) < (b) ? (a) : (b))
#define MATRIX_INDEX(x, y, cols) ((x) * (cols) + (y))

int *GenerateRowSums(int height, int width, int *matrix)
{
 int *result = calloc(height, sizeof(int));
 for(int i = 0; i < height; i++)
 {
  int sum = 0;
  for(int j = 0; j < width; j++)
  {
   sum += matrix[(i*width) + j];
  }
  result[i]=sum;
 }
 return result;
}

int *GenerateColumnSums(int height, int width, int *matrix)
{
 int *result = calloc(width, sizeof(int));
 for(int j = 0; j < width; j++)
 {
  int sum = 0;
  for(int i = 0; i < height; i++)
  {
   sum += matrix[(i*width) + j];
  }
  result[j] = sum;
 }
 return result;
}

void PrintIntArray_ChenDiaconis(int length, int *array)
{
 for(int i = 0; i < length; i++)
 {
  printf("%3d, ", array[i]);
 }
 printf("\n");
}

int RandRange(int lowerBound, int upperBound)
{
 return lowerBound + rand() % (upperBound - lowerBound + 1);
}

int MakeDecision(int currentColumnSum, int currentRowSum, int currentTotalSum, int *currentQ)
{
 int decision = 0;
 int lowerBound = MAX_ChenDiaconis(0, currentColumnSum + currentRowSum - currentTotalSum);
 int upperBound = MIN_ChenDiaconis(currentColumnSum, currentRowSum);
 decision = RandRange(lowerBound, upperBound);
 *currentQ = upperBound - lowerBound + 1;
 return decision;
}

void PrintTable_ChenDiaconis(int numberOfRows, int numberOfColumns, int *table)
{
 for(int i = 0; i < numberOfRows; i++)
 {
  for(int j = 0; j < numberOfColumns; j++)
  {
   printf("%3d, ", table[MATRIX_INDEX(i,j,numberOfColumns)]);
  }
  printf("\n");
 }
}

void GenerateTable(int numberOfRows, int numberOfColumns, int totalSum, int *rowSums, int *columnSums, int *tableHolder, mpz_t qT)
{
 mpz_t currentQ; mpz_init(currentQ);mpz_set_ui(currentQ, 1);
 int currentColumnSum = 0;
 int currentRowSum = 0;
 int currentTotalSum = 0;
 int currentTableValue = 0;
 int decision = 0;
 int qHolder = 0;
 for(int i = 0; i < numberOfColumns; i++)
 {
  currentColumnSum = columnSums[i];
  currentTotalSum = totalSum;
  for(int j = 0; j < numberOfRows; j++)
  {
   currentTableValue = tableHolder[MATRIX_INDEX(j,i,numberOfColumns)];
   currentRowSum = rowSums[j];
   decision = MakeDecision(currentColumnSum, currentRowSum, currentTotalSum, &qHolder);
   mpz_mul_ui(currentQ, currentQ, (unsigned long int) qHolder);
   tableHolder[MATRIX_INDEX(j,i,numberOfColumns)] = decision; 
   currentColumnSum -= decision;
   currentTotalSum  -= currentRowSum;
   rowSums[j] -= decision;
   totalSum -= decision;
  }
 }
 mpz_add(qT, qT, currentQ);
 mpz_clear(currentQ);
}

int TestDiaconis()
{
 srand(55455);
 int montecarloTrials = 10000;
 int numberOfRows = 5;
 int numberOfColumns = 3;
 mpz_t qT; mpz_init(qT);mpz_set_ui(qT, 0);
 int *tableHolder = calloc(numberOfRows *numberOfColumns, sizeof(int));

 tableHolder[MATRIX_INDEX(0,0,numberOfColumns)] = 5; tableHolder[MATRIX_INDEX(0,1,numberOfColumns)] = 2;tableHolder[MATRIX_INDEX(0,2,numberOfColumns)] = 3;
 tableHolder[MATRIX_INDEX(1,0,numberOfColumns)] = 50;tableHolder[MATRIX_INDEX(1,1,numberOfColumns)] = 7;tableHolder[MATRIX_INDEX(1,2,numberOfColumns)] = 5;
 tableHolder[MATRIX_INDEX(2,0,numberOfColumns)] = 3; tableHolder[MATRIX_INDEX(2,1,numberOfColumns)] = 6;tableHolder[MATRIX_INDEX(2,2,numberOfColumns)] = 4;
 tableHolder[MATRIX_INDEX(3,0,numberOfColumns)] = 5; tableHolder[MATRIX_INDEX(3,1,numberOfColumns)] = 3;tableHolder[MATRIX_INDEX(3,2,numberOfColumns)] = 3;
 tableHolder[MATRIX_INDEX(4,0,numberOfColumns)] = 2; tableHolder[MATRIX_INDEX(4,1,numberOfColumns)] = 7;tableHolder[MATRIX_INDEX(4,2,numberOfColumns)] = 30;
 int *rowSums = GenerateRowSums(numberOfRows, numberOfColumns, tableHolder);
 int *columnSums = GenerateColumnSums(numberOfRows, numberOfColumns, tableHolder);

 int *rowSumsCopy = GenerateRowSums(numberOfRows, numberOfColumns, tableHolder);
 int *columnSumsCopy = GenerateColumnSums(numberOfRows, numberOfColumns, tableHolder);

 int totalSum = 0; for(int i = 0; i < numberOfRows; i++){totalSum += rowSums[i];} 

 for(int i = 0; i < montecarloTrials; i++)
 {
  memcpy(rowSumsCopy, rowSums, numberOfRows * sizeof(int));
  memcpy(columnSumsCopy, columnSums, numberOfColumns * sizeof(int));
  GenerateTable(numberOfRows, numberOfColumns, totalSum, rowSumsCopy, columnSumsCopy, tableHolder, qT);
 }
 mpz_div_ui(qT, qT, (unsigned long int) montecarloTrials);
 gmp_printf("Approximate Count : %3Zd : %d\n", qT , 238243776);
 mpz_clear(qT);free(rowSums);free(columnSums);free(rowSumsCopy);free(columnSumsCopy);
 free(tableHolder);
 return 0;
}

int main()
{
 TestDiaconis();
 return 0;
}

메타데이터
post_id
d9fc7f427a0b
slug
paper-implementation-sequential-monte-carlo-methods-for-statistical-analysis-of-tables-d9fc7f427a0b
url
https://medium.com/@kibichomurage/paper-implementation-sequential-monte-carlo-methods-for-statistical-analysis-of-tables-d9fc7f427a0b
canonical_url
https://medium.com/@kibichomurage/paper-implementation-sequential-monte-carlo-methods-for-statistical-analysis-of-tables-d9fc7f427a0b
author_url
https://medium.com/@kibichomurage
status
ok
fetched_at
2026-07-23 04:11:16