#include <stdlib.h> #include <stdio.h> #include <math.h> #include <malloc.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, int *s0RowSum); static double SSquareBar(int **a, int NumRow, int NumCol); static void InitialSetting (double *pSampleMean, double *pSampleVar, int *pNumBad, double *pPValue); static void GenerateATable (int **t, int **s0, int NumRow, int NumCol, int *rowSum, int *colSum, int *s0RowSum, double *pCurrentSample, int *pBadSample); static void UpdatePValue (int badSample, double currentSample, int **t, int NumRow, int NumCol, double sSquare0Bar, double *pSampleMean, double *pSampleVar, double *pPValue, int *pNumBad); static void PrintOutput (FILE *outFile, int N, int numBad, double sampleMean, double sampleVar, double pValue); static double NChooseM(int n, int m); static double Mean(double x[], int n); static int RandomSample2(double weight[], int n); static double Drafting(int w[], int start, int end, int n, int a[], int s[], int NumRow); static int ChooseOneInteger(double w[], int start, int end, int NumRow); static double R(int k, double w[], int start, int end, int NumRow); static double T(int i, double w[], int start, int end); static double RandomReal(double low, double high); static int RandomInteger(int low, int high); main() { int i, NumRow, NumCol, M, N, numEstimate, numSample, numBad, badSample; double sampleMean, currentSample, cvsquare1, sampleVar; double sSquare0Bar, pValue; int **table, **t, **s0, *s0RowSum, *rowSum, *colSum; FILE *outFile; ReadInfo(&NumRow, &NumCol, &M, &N); //allocate space for pointers table=malloc(NumRow*sizeof(int *)); t=malloc(NumRow*sizeof(int *)); s0=malloc(NumRow*sizeof(int *)); rowSum=malloc(NumRow*sizeof(int)); colSum=malloc(NumCol*sizeof(int)); s0RowSum=malloc(NumRow*sizeof(int)); for (i=0; i<NumRow; i++) { table[i]=malloc(NumCol*sizeof(int)); t[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, s0RowSum); sSquare0Bar=SSquareBar(table, NumRow, NumCol); outFile=fopen("result.txt", "w"); if (outFile != NULL) { for (numEstimate=0; numEstimate<M; numEstimate++) { InitialSetting(&sampleMean, &sampleVar, &numBad, &pValue); for (numSample=0; numSample<N; numSample++) { GenerateATable(t, s0, NumRow, NumCol, rowSum, colSum, s0RowSum, ¤tSample, &badSample); UpdatePValue(badSample, currentSample, t, NumRow, NumCol, sSquare0Bar, &sampleMean, &sampleVar, &pValue, &numBad); } PrintOutput(outFile, N, numBad, 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, int *s0RowSum) { int i, j, k, m, n, temp; int *maxRange, *minRange; FILE *inFile; char nameInFile[256]; maxRange=malloc(NumRow*sizeof(int)); minRange=malloc(NumRow*sizeof(int)); 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++) { 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]; } } //change order of columns for (m=0; m<NumCol; m++) { k=m; for (n=m+1; n<NumCol; n++) { if (colSum[n]>colSum[k]) k=n; } temp=colSum[m]; colSum[m]=colSum[k]; colSum[k]=temp; for (i=0; i<NumRow; i++) { temp=table[i][m]; table[i][m]=table[i][k]; table[i][k]=temp; } } for (i=0; i<NumRow; i++) { maxRange[i]=-1; minRange[i]=NumRow+1; for (j=0; j<NumCol; j++) { if (table[i][j] == 1) { if (colSum[j]>maxRange[i]) maxRange[i]=colSum[j]; if (colSum[j]<minRange[i]) minRange[i]=colSum[j]; } } } for (i=0; i<NumRow; i++) { s0RowSum[i]=0; for (j=0; j<NumCol; j++) { if (colSum[j]<minRange[i] || colSum[j]>maxRange[i]) { s0[i][j]=1; s0RowSum[i]++; } else s0[i][j]=0; } } free(maxRange); free(minRange); } static double SSquareBar(int **a, int NumRow, int NumCol) { int i,j,k; double sum; int s; sum=0; for (i=0; i<NumRow; i++) { for (j=0; j<NumRow; j++) { s=0; for (k=0; k<NumCol; k++) { s=s+a[i][k]*a[j][k]; } if (j!=i) { sum=sum+s*s; } } } return (sum/NumRow/(NumRow-1)); } static void InitialSetting (double *pSampleMean, double *pSampleVar, int *pNumBad, double *pPValue) { *pSampleMean=0; *pSampleVar=0; *pNumBad=0; *pPValue=0; } static void GenerateATable (int **t, int **s0, int NumRow, int NumCol, int *rowSum, int *colSum, int *s0RowSum, double *pCurrentSample, int *pBadSample) { int j, k, m, badSample, count; int *currentRowSum, *currentS0RowSum, *index, *rowSegment, *leftoverCol; int *oneIndex; int currentColSum, numPosition, temp; double currentSample, prob; currentRowSum=malloc(NumRow*sizeof(int)); currentS0RowSum=malloc(NumRow*sizeof(int)); index=malloc(NumRow*sizeof(int)); rowSegment=malloc(NumRow*sizeof(int)); leftoverCol=malloc(NumRow*sizeof(int)); oneIndex=malloc(NumRow*sizeof(int)); for (j=0;j<NumRow; j++) { currentS0RowSum[j]=s0RowSum[j]; currentRowSum[j]=rowSum[j]; for (m=0; m<NumCol; m++) { t[j][m]=0; } } currentSample=1.0; badSample=0; for (j=0; j<NumCol; j++) { if (colSum[j]>0 && badSample==0) { count=0; currentColSum=colSum[j]; for (m=0; m<NumRow; m++) { numPosition=NumCol-j-currentS0RowSum[m]; if (numPosition<currentRowSum[m]) { badSample=1; break; } else if (s0[m][j]==1 || currentRowSum[m]==0) t[m][j]=0; else if (currentRowSum[m]>0 && currentRowSum[m]==numPosition) { t[m][j]=1; currentColSum--; } else { index[count]=m; rowSegment[count]=currentRowSum[m]; leftoverCol[count]=numPosition; count++; } } if (currentColSum<0 || currentColSum>count) { badSample=1; } if (badSample==1) break; if (count>0) { prob=Drafting(rowSegment,0,count-1,currentColSum,oneIndex, leftoverCol, NumRow); currentSample=currentSample/prob; for (k=0; k<currentColSum; k++) { t[index[oneIndex[k]]][j]=1; } } temp=0; for (m=0; m<NumRow; m++) { currentRowSum[m]=currentRowSum[m]-t[m][j]; currentS0RowSum[m]=currentS0RowSum[m]-s0[m][j]; temp=temp+t[m][j]; } if (temp != colSum[j]) { badSample=1; break; } } if (colSum[j]==0) { for (m=0; m<NumRow; m++) { currentS0RowSum[m]=currentS0RowSum[m]-s0[m][j]; } } } if (badSample==0) { for (m=0; m<NumRow; m++) { if ((currentRowSum[m]>1) || (s0[m][j]==1 && currentRowSum[m]>0)) badSample=1; } } *pCurrentSample=currentSample; *pBadSample=badSample; free(currentRowSum); free(currentS0RowSum); free(index); free(rowSegment); free(leftoverCol); free(oneIndex); } static void UpdatePValue (int badSample, double currentSample, int **t, int NumRow, int NumCol, double sSquare0Bar, double *pSampleMean, double *pSampleVar, double *pPValue, int *pNumBad) { if (badSample==0) { (*pSampleMean) = (*pSampleMean)+currentSample; (*pSampleVar)=(*pSampleVar)+currentSample*currentSample; if (SSquareBar(t, NumRow, NumCol)>=sSquare0Bar) (*pPValue)=(*pPValue)+currentSample; } else { (*pNumBad)++; } } static void PrintOutput (FILE *outFile, int N, int numBad, double sampleMean, double sampleVar, double pValue) { double cvsquare1; cvsquare1=(N-numBad)*sampleVar/sampleMean/sampleMean-1; pValue=pValue/sampleMean; sampleMean=sampleMean/N; fprintf(outFile, "%15g %15g %15g %10d\n", sampleMean, pValue, cvsquare1, numBad); printf("%15g %15g %15g %10d\n", sampleMean, pValue, cvsquare1, numBad); } static double NChooseM(int n, int m) { int i; double value; value=1.0; if ((m<=0) || (n<=0) || (n<m)) return(value); 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 RandomSample2(double weight[], int n) { int low, up, mid; double randomNum; randomNum=RandomReal(0, weight[n-1]); low=0; up=n-1; mid=n/2; while (1) { if (randomNum>=weight[mid]) { low=mid+1; mid=(mid+up)/2; if (low==up) { mid=up; break; } } else if ((mid>0) && (randomNum<weight[mid-1])) { up=mid-1; mid=(mid+low)/2; } else break; } return (mid); } static double Drafting(int w[], int start, int end, int n, int a[], int s[], int NumRow) { double *p, *newP; int i,j; double tmp; double prob; double *currentWeight; double r1, r2; double *weight; p=malloc(NumRow*sizeof(double)); newP=malloc(NumRow*sizeof(double)); currentWeight=malloc(NumRow*sizeof(double)); weight=malloc(NumRow*sizeof(double)); if (n==0) return (1); if (end-start+1==n) { for (i=start; i<=end; i++) { a[i-start]=i; } return(1); } for (i=start; i<=end; i++) { if (w[i]==0) { weight[i]=0; } else { weight[i]=exp(log(1.0*w[i]/(s[i]-w[i]))); } } for (i=start; i<=end; i++) { tmp=weight[i]; weight[i]=weight[end]; p[i]=tmp*R(n-1, weight, start, end-1, NumRow); weight[i]=tmp; currentWeight[i]=weight[i]; } a[0]=ChooseOneInteger(p, start, end, NumRow); currentWeight[a[0]]=0; j=0; while (n>(j+1)) { for (i=start; i<=end; i++) { if (currentWeight[i]<=0.00000000001) newP[i]=0; else if (abs(weight[i]-weight[a[j]])<0.0000000001) { currentWeight[i]=0; r1=R(n-j-2, currentWeight, start, end, NumRow); currentWeight[i]=weight[i]; r2=R(n-j-1, currentWeight, start, end, NumRow); newP[i]=weight[i]*r1/(n-j-1)/r2; } else { newP[i]=(weight[a[j]]*p[i]-weight[i]*p[a[j]])/(n-j-1)/(weight[a[j]]-weight[i])/p[a[j]]; } } j++; a[j]=ChooseOneInteger(newP, start, end, NumRow); currentWeight[a[j]]=0; for (i=start; i<=end; i++) { p[i]=newP[i]; } } prob=1; for (i=0; i<n; i++) { prob=prob*weight[a[i]]; } prob=prob/R(n, weight, start, end, NumRow); free(p); free(newP); free(currentWeight); free(weight); return(prob); } static int ChooseOneInteger(double weight[], int start, int end, int NumRow) { int i; double *totalWeight, temp; totalWeight=malloc(NumRow*sizeof(double)); totalWeight[start]=weight[start]; for (i=start+1; i<=end; i++) { totalWeight[i]=totalWeight[i-1]+weight[i]; } temp=RandomReal(0,totalWeight[end]); i=start; while (totalWeight[i]<=temp) { i++; } free(totalWeight); return (i); } static double R(int k, double w[], int start, int end, int NumRow) { int i, j; double *t; double *r, temp; t=malloc((NumRow+1)*sizeof(double)); r=malloc(NumRow*sizeof(double)); for (i=1; i<=k; i++) { t[i]=T(i, w, start, end); } r[0]=1; for (j=1; j<=k; j++) { r[j]=0; for (i=1; i<=j; i++) { if (i%2==0) r[j]=r[j]-t[i]*r[j-i]; else r[j]=r[j]+t[i]*r[j-i]; } r[j]=r[j]/j; } temp=r[k]; free(t); free(r); return (temp); } static double T(int i, double w[], int start, int end) { double sum; int j, k; double tmp; sum=0; for (j=start; j<=end; j++) { tmp=1.0; for (k=0; k<i; k++) { tmp=tmp*w[j]; } sum = sum+tmp; } return (sum); } 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); } static double RandomReal(double low, double high) { double d; d=(double) rand()/((double) RAND_MAX+1); return (low+d*(high-low)); }