#include "stdlib.h"
#include "stdio.h"
#include <math.h>
#include <time.h>
static void ReadInfo(int *pNumRow, int *pNumCol, int *pM, int *pN);
static void ReadTable (int NumRow, int NumCol, int **table, int *rowSum,
int *colSum, int **s0, float **mle);
static double ChiSquareStatistic(int **t, int **s0, float **mle, int NumRow,
int NumCol);
static void InitialSetting (double *pSampleMean, double *pSampleVar,
double *pPValue);
static void GenerateATable (int **table, int **s0, int NumRow, int NumCol,
int *rowSum, int *colSum, double *pCurrentWeight);
static void UpdatePValue (double currentWeight, int **table, int **s0,
float **mle, int NumRow, int NumCol,
double chiSquare0, double *pSampleMean,
double *pSampleVar, double *pPValue);
static void PrintOutput (FILE *outFile, int N, double sampleMean,
double sampleVar, double pValue);
static double NChooseM(int n, int m);
static double Mean(double x[], int n);
static int RandomInteger(int low, int high);
main()
{
int i, NumRow, NumCol, M, N, numEstimate, numSample;
int *rowSum, *colSum, **table, **s0;
float **mle;
FILE *outFile;
double sampleMean, sampleVar, chiSquare0, chiSquare, pValue,
currentWeight;
ReadInfo(&NumRow, &NumCol, &M, &N);
//allocate space for pointers
rowSum=malloc(NumRow*sizeof(int));
colSum=malloc(NumCol*sizeof(int));
mle=malloc(NumRow*sizeof(float *));
table=malloc(NumRow*sizeof(int *));
s0=malloc(NumRow*sizeof(int *));
for (i=0; i<NumRow; i++) {
mle[i]=malloc(NumCol*sizeof(float));
table[i]=malloc(NumCol*sizeof(int));
s0[i]=malloc(NumCol*sizeof(int));
}
//end of allocation
srand((int) time(NULL));
ReadTable(NumRow, NumCol, table, rowSum, colSum, s0, mle);
chiSquare0=ChiSquareStatistic(table, s0, mle, NumRow, NumCol);
outFile=fopen("result.txt", "w");
if (outFile != NULL) {
for (numEstimate=0; numEstimate<M; numEstimate++) {
InitialSetting(&sampleMean, &sampleVar, &pValue);
for (numSample=0; numSample<N; numSample++) {
GenerateATable(table, s0, NumRow, NumCol, rowSum, colSum,
¤tWeight);
UpdatePValue(currentWeight, table, s0, mle, NumRow, NumCol,
chiSquare0, &sampleMean, &sampleVar, &pValue);
}
PrintOutput(outFile, N, sampleMean, sampleVar, pValue);
}
}
else { printf("File creating failed!\n");}
fclose(outFile);
}
static void ReadInfo(int *pNumRow, int *pNumCol, int *pM, int *pN)
{
int NumRow, NumCol, M, N;
printf("\nPlease enter the number of rows in the table?\n");
scanf("%d", &NumRow);
printf("\nPlease enter the number of columns in the table?\n");
scanf("%d", &NumCol);
printf("\nHow many estimates do you need?\n");
scanf("%d", &M);
printf("\nHow many samples should each estimate be based on?\n");
scanf("%d", &N);
*pNumRow=NumRow;
*pNumCol=NumCol;
*pM=M;
*pN=N;
}
static void ReadTable (int NumRow, int NumCol, int **table, int *rowSum,
int *colSum, int **s0, float **mle)
{
int i, j;
FILE *inFile;
char nameInFile[256];
printf("\nPlease enter the data file name:\n");
scanf("%s", nameInFile);
while((inFile=fopen(nameInFile, "r"))==NULL)
{
printf("\nCan't read file. Please enter the data file name:\n");
scanf("%s", nameInFile);
}
for (i=0; i<NumRow; i++) {
for (j=0; j<NumCol; j++) {
fscanf(inFile, "%d", &table[i][j]);
}
}
for (i=0; i<NumRow; i++) {
for (j=0; j<NumCol; j++) {
fscanf(inFile, "%d", &s0[i][j]);
}
}
for (i=0; i<NumRow; i++) {
for (j=0; j<NumCol; j++) {
fscanf(inFile, "%f", &mle[i][j]);
}
}
for (i=0; i<NumRow; i++) {
rowSum[i]=0;
for (j=0; j<NumCol; j++) {
rowSum[i]=rowSum[i]+table[i][j];
}
}
for (j=0; j<NumCol; j++) {
colSum[j]=0;
for (i=0; i<NumRow; i++) {
colSum[j]=colSum[j]+table[i][j];
}
}
}
static double ChiSquareStatistic(int **t, int **s0, float **tmp, int NumRow,
int NumCol)
{
double sum;
int i,j;
sum=0;
for (i=0; i<NumRow; i++) {
for (j=0; j<NumCol; j++) {
if (s0[i][j] == 0)
sum=sum+(t[i][j]-tmp[i][j])*(t[i][j]-tmp[i][j])/tmp[i][j];
}
}
return (sum);
}
static void InitialSetting (double *pSampleMean, double *pSampleVar,
double *pPValue)
{
*pSampleMean=0;
*pSampleVar=0;
*pPValue=0;
}
static void GenerateATable (int **table, int **s0, int NumRow, int NumCol,
int *rowSum, int *colSum, double *pCurrentWeight)
{
int j, k, m, temp, leftColSum, max, min;
int *currentRowSum, *upper, *lower, *leftLowerWeight, *leftUpperWeight;
double currentWeight;
currentRowSum=malloc(NumRow*sizeof(int));
lower=malloc((NumRow+1)*sizeof(int));
upper=malloc((NumRow+1)*sizeof(int));
leftUpperWeight=malloc((NumRow+1)*sizeof(int));
leftLowerWeight=malloc((NumRow+1)*sizeof(int));
for (j=0;j<NumRow; j++) {
currentRowSum[j]=rowSum[j];
}
currentWeight=1.0;
for (j=0; j<NumCol-1; j++) {
if (colSum[j]>0) {
for (k=0; k<NumRow; k++) {
upper[k] = 0;
lower[k] = 0;
if (s0[k][j] == 0) {
temp=currentRowSum[k];
for (m=j+1; m<NumCol; m++) {
if (s0[k][m]==0) temp=temp-colSum[m];
}
if (temp>0) lower[k]=temp;
upper[k]=(currentRowSum[k]<colSum[j])? currentRowSum[k] : colSum[j];
}
}
leftColSum=colSum[j];
leftLowerWeight[NumRow]=0;
leftUpperWeight[NumRow]=0;
for (k=NumRow-1; k>=0; k--) {
leftUpperWeight[k]=leftUpperWeight[k+1]+upper[k];
leftLowerWeight[k]=leftLowerWeight[k+1]+lower[k];
}
for (k=0; k<NumRow-1; k++) {
if (s0[k][j]==1) table[k][j]=0;
else {
min=(lower[k]>=leftColSum-leftUpperWeight[k+1])?
lower[k]: (leftColSum-leftUpperWeight[k+1]);
max=(upper[k] <=
leftColSum-leftLowerWeight[k+1])? upper[k] : (leftColSum-leftLowerWeight[k+1]);
if (min>max) printf("Cannot sample!");
table[k][j]=RandomInteger(min, max);
leftColSum=leftColSum-table[k][j];
currentWeight=currentWeight*(max-min+1);
}
}
if (leftColSum != 0 && s0[NumRow-1][j]==1) printf("Inconsistent!!!");
else table[NumRow-1][j]=leftColSum;
for (k=0; k<NumRow; k++) {
currentRowSum[k]=currentRowSum[k]-table[k][j];
}
}
else {
for (k=0; k<NumRow; k++)
table[k][j]=0;
}
}
for (k=0; k<NumRow; k++) {
if (s0[k][NumCol-1]==1 && currentRowSum[k] !=0)
printf("Error!");
else table[k][NumCol-1]=currentRowSum[k];
}
*pCurrentWeight=currentWeight;
free(currentRowSum);
free(lower);
free(upper);
free(leftUpperWeight);
free(leftLowerWeight);
}
static void UpdatePValue (double currentWeight, int **table, int **s0,
float **mle, int NumRow, int NumCol,
double chiSquare0, double *pSampleMean,
double *pSampleVar, double *pPValue)
{
double chiSquare;
(*pSampleMean) = (*pSampleMean)+currentWeight;
(*pSampleVar)=(*pSampleVar)+currentWeight*currentWeight;
chiSquare=ChiSquareStatistic(table, s0, mle, NumRow, NumCol);
if (chiSquare<=chiSquare0) (*pPValue)=(*pPValue)+currentWeight;
}
static void PrintOutput (FILE *outFile, int N, double sampleMean,
double sampleVar, double pValue)
{
double cvsquare;
pValue=pValue/sampleMean;
cvsquare=N*sampleVar/sampleMean/sampleMean-1;
sampleMean=sampleMean/N;
fprintf(outFile, "%15g %15g %15g\n", sampleMean, pValue, cvsquare);
printf("%15g %15g %15g\n", sampleMean, pValue, cvsquare);
}
static double NChooseM(int n, int m)
{
int i;
double value;
value=1.0;
if ((m<0) || (n<0) || (n<m)) return(0);
if (m==0) return(1.0);
for (i=1; i<=m; i++) {
value=value*(n-i+1)/i;
}
return (value);
}
static double Mean(double x[], int n)
{
int i;
double sum=0;
for(i=0; i<n; i++) sum = sum+x[i];
return (sum/n);
}
static int RandomInteger(int low, int high)
{
int k;
double d;
d=(double) rand()/((double) RAND_MAX+1);
k=(int) (d*(high-low+1));
return (low+k);
}