/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { int N = n / M; //number of blocks that can be made from the binary string //for each block calculate the proportion of ones double sum = 0.0; for (int i = 0; i < N; i++) { double pi = (double)model.epsilon.GetRange(i * M, M).Sum() / (double)M; //sum of bits in block / length of the block sum += Math.Pow((pi - 0.5), 2); } //calculate p_value double chi_squared = 4.0 * M * sum; double p_value = Cephes.igamc(N / 2.0, chi_squared / 2.0); if (printResults) { Report report = new Report("2: Frequency Test within a Block"); report.Write("\t\t\tBLOCK FREQUENCY TEST"); report.Write("\t\t---------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t---------------------------------------------"); report.Write("\t\t(a) Chi^2 = " + chi_squared); report.Write("\t\t(b) # of substrings = " + N); report.Write("\t\t(c) block length = " + M); report.Write("\t\t(d) Note: " + n % M + " bits were discarded."); report.Write("\t\t---------------------------------------------"); report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value = " + p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { //calculate all psi_squares double psim0 = psi2(m, n); double psim1 = psi2(m - 1, n); double psim2 = psi2(m - 2, n); double del1 = psim0 - psim1; double del2 = psim0 - 2.0 * psim1 + psim2; //calculate p_values double p_value1 = Cephes.igamc(Math.Pow(2, m - 1) / 2, del1 / 2.0); double p_value2 = Cephes.igamc(Math.Pow(2, m - 2) / 2, del2 / 2.0); if (printResults) { Report report = new Report("11: Serial Test"); report.Write("\t\t\t SERIAL TEST"); report.Write("\t\t---------------------------------------------"); report.Write("\t\t COMPUTATIONAL INFORMATION: "); report.Write("\t\t---------------------------------------------"); report.Write("\t\t(a) Block length (m) = " + m); report.Write("\t\t(b) Sequence length (n) = " + n); report.Write("\t\t(c) Psi_m = " + psim0); report.Write("\t\t(d) Psi_m-1 = " + psim1); report.Write("\t\t(e) Psi_m-2 = " + psim2); report.Write("\t\t(f) Del_1 = " + del1); report.Write("\t\t(g) Del_2 = " + del2); report.Write("\t\t---------------------------------------------\n"); report.Write(p_value1 < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value1 = " + p_value1); report.Write(p_value2 < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value2 = " + p_value2); model.reports.Add(report.title, report); } return new double[] { p_value1, p_value2 }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { double pi = (double)model.epsilon.GetRange(0, n).Sum() / (double)n; //number of ones in the binary string / length //prerequisite for test, if not passed test is not applicable if (Math.Abs(pi - 0.5) > (2.0 / Math.Sqrt(n))) { if (printResults) { Report report = new Report("3: Runs Test"); report.Write("\t\t\t\tRUNS TEST"); report.Write("\t\t------------------------------------------"); report.Write("\t\tPI ESTIMATOR CRITERIA NOT MET! PI = " + pi); model.reports.Add(report.title, report); } return new double[] { 0.0 }; } else { //count number of runs in the binary string (where e(i) = e(i+1) is considered to be a run) int V_obs = 1; for (int i = 1; i < n; i++) { if (model.epsilon[i] != model.epsilon[i - 1]) { V_obs++; } } //calculate p_value double p_value = Cephes.erfc(Math.Abs(V_obs - 2.0 * n * pi * (1 - pi)) / (2.0 * pi * (1 - pi) * Math.Sqrt(2 * n))); if (printResults) { Report report = new Report("3: Runs Test"); report.Write("\t\t\t\tRUNS TEST"); report.Write("\t\t------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t------------------------------------------"); report.Write("\t\t(a) Pi = " + pi); report.Write("\t\t(b) V_n_obs (Total # of runs) = " + (int)V_obs); report.Write("\t\t(c) V_n_obs - 2 n pi (1-pi)", false); report.Write("\t\t 2 sqrt(2n) pi (1-pi)"); report.Write("\t\t------------------------------------------"); if (p_value < 0 || p_value > 1) { report.Write("WARNING: P_VALUE IS OUT OF RANGE."); } report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS"+"\t\tp_value = "+p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; } }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { //calculate the sum of all bits in the string after mapping (0->-1, 1->1) double S_n = model.epsilon.GetRange(0, n).Sum(delegate(int i) { return 2 * i - 1; }); //calculate p_value double S_obs = Math.Abs(S_n) / Math.Sqrt(n); double p_value = Cephes.erfc(S_obs / Math.Sqrt(2)); if (printResults) { Report report = new Report("1: Frequency (Monobit) Test"); report.Write("\t\t\t FREQUENCY TEST"); report.Write("\t\t---------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t---------------------------------------------"); report.Write("\t\t(a) The nth partial sum = " + (int)S_n); report.Write("\t\t(b) S_n/n = " + S_n / n); report.Write("\t\t---------------------------------------------"); report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value = " + p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { int[] stateX = { -4, -3, -2, -1, 1, 2, 3, 4 }; double[,] pi = { {0.0000000000, 0.00000000000, 0.00000000000, 0.00000000000, 0.00000000000, 0.0000000000}, {0.5000000000, 0.25000000000, 0.12500000000, 0.06250000000, 0.03125000000, 0.0312500000}, {0.7500000000, 0.06250000000, 0.04687500000, 0.03515625000, 0.02636718750, 0.0791015625}, {0.8333333333, 0.02777777778, 0.02314814815, 0.01929012346, 0.01607510288, 0.0803755143}, {0.8750000000, 0.01562500000, 0.01367187500, 0.01196289063, 0.01046752930, 0.0732727051} }; Report report = new Report("14: Random Excursions Test"); //determine cycles int J = 0; int[] S_k = new int[n]; S_k[0] = 2 * (int)model.epsilon[0] - 1; int[] cycle = new int[Math.Max(1000, n / 100)]; for (int i = 1; i < n; i++) { S_k[i] = S_k[i - 1] + 2 * model.epsilon[i] - 1; if (S_k[i] == 0) { J++; if (J > Math.Max(1000, n / 100)) { if (printResults) { report.Write("ERROR IN FUNCTION randomExcursions: EXCEEDING THE MAX NUMBER OF CYCLES EXPECTED."); } return null; } cycle[J] = i; } } if (S_k[n - 1] != 0) { J++; } cycle[J] = n; if (printResults) { report.Write("\t\t\t RANDOM EXCURSIONS TEST"); report.Write("\t\t--------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t--------------------------------------------"); report.Write("\t\t(a) Number Of Cycles (J) = " + J); report.Write("\t\t(b) Sequence Length (n) = " + n); } double constraint = Math.Max(0.005 * Math.Pow(n, 0.5), 500); double[] p_values = new double[8]; if (J < constraint) { if (printResults) { report.Write("\t\t---------------------------------------------"); report.Write("\t\tWARNING: TEST NOT APPLICABLE. THERE ARE AN"); report.Write("\t\t\t INSUFFICIENT NUMBER OF CYCLES."); report.Write("\t\t---------------------------------------------"); for (int i = 0; i < 8; i++) { report.Write(0.0.ToString()); } } } else { if (printResults) { report.Write("\t\t(c) Rejection Constraint = " + constraint); report.Write("\t\t-------------------------------------------"); } double[,] v = new double[6, 8]; int cycleStart = 0; int cycleStop = cycle[1]; for (int k = 0; k < 6; k++) { for (int i = 0; i < 8; i++) { v[k, i] = 0.0; } } int[] counter = new int[8]; //for each cycle compute frequency of x for (int j = 1; j <= J; j++) { for (int i = 0; i < 8; i++) { counter[i] = 0; } for (int i = cycleStart; i < cycleStop; i++) { if ((S_k[i] >= 1 && S_k[i] <= 4) || (S_k[i] >= -4 && S_k[i] <= -1)) { int b = S_k[i]<0 ? 4 : 3; counter[S_k[i] + b]++; } } cycleStart = cycle[j] + 1; if (j < J) { cycleStop = cycle[j + 1]; } for (int i = 0; i < 8; i++) { if ((counter[i] >= 0) && (counter[i] <= 4)) { v[counter[i], i]++; } else if (counter[i] >= 5) { v[5, i]++; } } } //calculate p_values for (int i = 0; i < 8; i++) { int x = stateX[i]; double sum = 0; for (int k = 0; k < 6; k++) { sum += Math.Pow(v[k, i] - J * pi[(int)Math.Abs(x), k], 2) / (J * pi[(int)Math.Abs(x), k]); } p_values[i] = Cephes.igamc(2.5, sum / 2.0); if (printResults) { if (p_values[i] < 0 || p_values[i] > 1) { report.Write("WARNING: P_VALUE IS OUT OF RANGE."); } report.Write(p_values[i] < ALPHA ? "FAILURE" : "SUCCESS"+"\t\tx = "+x+" chi^2 = "+sum+" p_value = "+p_values[i]); } } } if (printResults) { model.reports.Add(report.title, report); } return p_values; }
private double[] run(int[] B, bool printResults) { if (n > model.epsilon.Count || n <= 0) { throw new ArgumentException("The value of n must be smaller than the size of the input data, and be greater than 0", "Frequency n"); } int[] Wj = new int[N]; for (int i = 0; i < N; i++) { //for each start position for (int j = 0; j < M - B.Length + 1; j++) { //is there a match for the template bool match = true; for (int k = 0; k < B.Length; k++) { if ((int)B[k] != (int)model.epsilon[i * M + j + k]) { match = false; break; } } if (match) { Wj[i]++; //if there was a match, record it } } } //calculate p_value double chi2 = 0.0; for (int i = 0; i < N; i++) { chi2 += Math.Pow(((double)Wj[i] - mu) / Math.Pow(sigma, 0.5), 2); } double p_value = Cephes.igamc(N / 2.0, chi2 / 2.0); if (printResults) { Report report = new Report("7: Non-overlapping Template Matching Test"); report.Write("chi^2 = " + chi2); report.Write("p_value = " + p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> /// <exception cref="ArgumentException"/> /// <exception cref="FormatException"/> /// <exception cref="OverflowException"/> /// <exception cref="FileNotFoundException"/> /// <exception cref="DirectoryNotFoundException"/> /// <exception cref="UnauthorizedAccessException"/> /// <exception cref="IOException"/> /// <exception cref="OutOfMemoryException"/> public override double[] run(bool printResults) { if (B != null) { //as we know it is to run on a single test mu = (M - B.Length + 1) / Math.Pow(2, B.Length); sigma = M * (1.0 / Math.Pow(2.0, B.Length) - (2.0 * B.Length - 1.0) / Math.Pow(2.0, 2.0 * B.Length)); return run(B, printResults); } //otherwise on a template of tests int[] numOfTemplates = {0, 0, 2, 4, 6, 12, 20, 40, 74, 148, 284, 568, 1116, 2232, 4424, 8848, 17622, 35244, 70340, 140680, 281076, 562152}; //compute predicted probabilities int K = 5; mu = (M - m + 1) / Math.Pow(2, m); sigma = M * (1.0 / Math.Pow(2.0, m) - (2.0 * m - 1.0) / Math.Pow(2.0, 2.0 * m)); Report report = new Report("7: Non-overlapping Template Matching Test"); if (printResults) { report.Write("\t\t NONPERIODIC TEMPLATES TEST"); report.Write("-------------------------------------------------------------------------------------"); report.Write("\t\t COMPUTATIONAL INFORMATION"); report.Write("-------------------------------------------------------------------------------------"); report.Write("\tLAMBDA = " + mu + "\tM = " + M + "\tN = " + N + "\tm = " + m + "\tn = " + n + ""); report.Write("-------------------------------------------------------------------------------------"); } double[] p_values = new double[numOfTemplates[m]]; try { using (StreamReader sr = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(TEMPLATE_DIR + ".template" + m))) { for (int i = 0; i < numOfTemplates[m]; i++) { String line = sr.ReadLine(); //load in the template string String[] numbers = Regex.Split(line, TEMPLATESPLITSTR); B = new int[m]; for (int k = 0; k < m; k++) { try { B[k] = Convert.ToInt32(numbers[k]); //parse into an array } catch (FormatException) { throw new FormatException("The input data did not consist of a an optional " + "sign followed by a sequence of digits (0 through 9):\r\n\r\n" + line); } catch (OverflowException) { throw new OverflowException("The input string was not of a number within the program's ranges:\r\n\r\n" + line); } } p_values[i] = this.run(B, false)[0]; //get p_value for this template string if (printResults) { if (p_values[i] < 0 || p_values[i] > 1) { report.Write("\t\tWARNING: P_VALUE IS OUT OF RANGE."); } report.Write(i + "\t: " + (p_values[i] < ALPHA ? "FAILURE" : "SUCCESS") + "\t\t" + p_values[i]); } } } } catch (ArgumentException) { throw new ArgumentException("The input file path is not a valid one:\r\n\r\n" + TEMPLATE_DIR + "template" + m); } catch (FileNotFoundException) { throw new FileNotFoundException("The input file does not exist:\r\n\r\n" + TEMPLATE_DIR + "template" + m); } catch (DirectoryNotFoundException) { throw new DirectoryNotFoundException("The input directory does not exist:\r\n\r\n" + TEMPLATE_DIR + "template" + m); } catch (UnauthorizedAccessException) { throw new UnauthorizedAccessException("The user does not have the permissions to access this file:\r\n\r\n" + TEMPLATE_DIR + "template" + m); } catch (IOException) { throw new IOException("Failed to read from file successfully:\r\n\r\n" + TEMPLATE_DIR + "template" + m); } catch (OutOfMemoryException) { throw new OutOfMemoryException("System out of memory"); } model.reports.Add(report.title, report); return p_values; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { double[] pi = { 0.01047, 0.03125, 0.12500, 0.50000, 0.25000, 0.06250, 0.020833 }; int N = n/M; //number of blocks double mu = M / 2.0 + (9.0 + Math.Pow(-1, M+1)) / 36.0 - 1.0 / Math.Pow(2, M) * (M / 3.0 + 2.0 / 9.0); double[] v = new double[K+1]; for ( int i=0; i<N; i++ ) { int[] T = new int[M]; //initialize the work arrays int[] P = new int[M]; int[] C = new int[M]; int[] B = new int[M]; int L = 0; int m = -1; int d = 0; C[0] = 1; B[0] = 1; //calculate the linear complexity of the block int blockPos = 0; while ( blockPos < M ) { d = (int)model.epsilon[i * M + blockPos]; for (int j = 1; j <= L; j++) { d += C[j] * model.epsilon[i * M + blockPos - j]; } d = d % 2; if ( d == 1 ) { for (int j = 0; j < M; j++) { T[j] = C[j]; P[j] = 0; } for (int j = 0; j < M; j++) { if (B[j] == 1) { P[j + blockPos - m] = 1; } } for (int j = 0; j < M; j++) { C[j] = (C[j] + P[j]) % 2; } if ( L <= blockPos/2 ) { L = blockPos + 1 - L; m = blockPos; for (int j = 0; j < M; j++) { B[j] = T[j]; } } } blockPos++; } double Ti = Math.Pow(-1, M) * (L - mu) + 2.0 / 9.0; //record result of complexity test if ( Ti <= -2.5 ) v[0]++; else if ( Ti > -2.5 && Ti <= -1.5 ) v[1]++; else if ( Ti > -1.5 && Ti <= -0.5 ) v[2]++; else if ( Ti > -0.5 && Ti <= 0.5 ) v[3]++; else if ( Ti > 0.5 && Ti <= 1.5 ) v[4]++; else if ( Ti > 1.5 && Ti <= 2.5 ) v[5]++; else v[6]++; } //calculate p_value double chi_squared = 0; for (int i = 0; i < K + 1; i++) { chi_squared += Math.Pow(v[i] - N * pi[i], 2) / (N * pi[i]); } double p_value = Cephes.igamc(K/2.0, chi_squared/2.0); if (printResults) { Report report = new Report("10: Linear Complexity Test"); report.Write("-----------------------------------------------------"); report.Write("\tL I N E A R C O M P L E X I T Y"); report.Write("-----------------------------------------------------"); report.Write("\tM (substring length) = {0}" + M); report.Write("\tN (number of substrings) = {0}" + N); report.Write("-----------------------------------------------------"); report.Write(" F R E Q U E N C Y "); report.Write("-----------------------------------------------------"); report.Write(" C0 C1 C2 C3 C4 C5 C6 CHI2 P-value"); report.Write("-----------------------------------------------------"); report.Write("\tNote: " + n % M + " bits were discarded!"); for (int i = 0; i < K + 1; i++) { report.Write(((int)v[i]).ToString(), false); } report.Write(""); report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value = " + p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { int[] stateX = { -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int J = 0; int[] S = new int[n]; //compute partial sums S[0] = 2 * (int)model.epsilon[0] - 1; for (int i = 1; i < n; i++) { S[i] = S[i - 1] + 2 * model.epsilon[i] - 1; if (S[i] == 0) { J++; } } if (S[n - 1] != 0) { J++; } Report report = new Report("15: Random Excursions Variant Test"); if (printResults) { report.Write("\t\t\tRANDOM EXCURSIONS VARIANT TEST"); report.Write("\t\t--------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t--------------------------------------------"); report.Write("\t\t(a) Number Of Cycles (J) = " + J); report.Write("\t\t(b) Sequence Length (n) = " + n); } double[] p_values = new double[18]; int constraint = (int)Math.Max(0.005 * Math.Pow(n, 0.5), 500); if (J < constraint) { if (printResults) { report.Write("\t\tWARNING: TEST NOT APPLICABLE. THERE ARE AN"); report.Write("\t\t\t INSUFFICIENT NUMBER OF CYCLES."); report.Write("\t\t---------------------------------------------"); } for (int i = 0; i < 18; i++) { report.Write(0.0.ToString()); } } else { for (int p = 0; p < 18; p++) { int x = stateX[p]; int count = 0; //count occurences of state x for (int i = 0; i < n; i++) { if (S[i] == x) { count++; } } //compute p_value p_values[p] = Cephes.erfc(Math.Abs(count - J) / (Math.Sqrt(2.0 * J * (4.0 * Math.Abs(x) - 2)))); if (printResults) { if (p_values[p] < 0 || p_values[p] > 1) { report.Write("\t\t(b) WARNING: P_VALUE IS OUT OF RANGE."); } report.Write(p_values[p] < ALPHA ? "FAILURE" : "SUCCESS" + "\t\t"); report.Write("(x = " + x + ") Total visits = " + count + "; p-value = " + p_values[p]); report.Write(p_values[p].ToString()); } } } if (printResults) { model.reports.Add(report.title, report); } return p_values; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { int r = 0; double[] apEn = new double[2]; for ( int blockSize=m; blockSize<=m+1; blockSize++ ) { if ( blockSize == 0 ) { apEn[0] = 0; r++; } else { int[] P = new int[(int)Math.Pow(2, blockSize+1)-1]; for (int i = 1; i < Math.Pow(2, blockSize + 1) - 1; i++) { P[i] = 0; } //calculate frequency of n overlapping blocks for (int i = 0; i < n; i++) { int k = 1; for (int j = 0; j < blockSize; j++) { k *= 2; if ((int)model.epsilon[(i + j) % n] == 1) { k++; } } P[k - 1]++; } //calculate approximate entropy entry from frequency double sum = 0; int index = (int)Math.Pow(2, blockSize)-1; for ( int i=0; i<(int)Math.Pow(2, blockSize); i++ ) { if (P[index] > 0) { sum += P[index] * Math.Log(P[index] / (double)n); } index++; } apEn[r] = sum / n; r++; } } double approximateEntropy = apEn[0] - apEn[1]; //calculate p_value double chi_squared = 2.0*n*(Math.Log(2) - approximateEntropy); double p_value = Cephes.igamc(Math.Pow(2, m-1), chi_squared/2.0); if (printResults) { Report report = new Report("12: Approximate Entropy Test"); report.Write("\t\t\tAPPROXIMATE ENTROPY TEST"); report.Write("\t\t--------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t--------------------------------------------"); report.Write("\t\t(a) m (block length) = "+ m); report.Write("\t\t(b) n (sequence length) = " + n); report.Write("\t\t(c) Chi^2 = " + chi_squared); report.Write("\t\t(d) Phi(m) = " + apEn[0]); report.Write("\t\t(e) Phi(m+1) = " + apEn[1]); report.Write("\t\t(f) ApEn = " + approximateEntropy); report.Write("\t\t--------------------------------------------"); if (m > (int)(Math.Log(n) / Math.Log(2) - 5)) { report.Write("\t\tNote: The blockSize = "+m+" exceeds recommended value of "+ Math.Max(1, (int)(Math.Log(n) / Math.Log(2) - 5))); report.Write("\t\tResults are inaccurate!"); report.Write("\t\t--------------------------------------------"); } report.Write((p_value < ALPHA ? "FAILURE" : "SUCCESS")+"\t\tp_value = "+ p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { double[] pi; int K, M, V0; init(out K, out M, out V0, out pi); //initialize variables to sensible values int[] V = new int[pi.Length]; int N = n / M; //number of blocks that can be made from the binary string for (int i = 0; i < N; i++) { //count the longest run of ones in each block int longestRun = 0; int currentRun = 0; for (int j = 0; j < M; j++) { if (model.epsilon[i * M + j] == 1) { longestRun = Math.Max(longestRun, ++currentRun); } else { currentRun = 0; } } //record the longest run of ones found in the correct counter if (longestRun < V0) { V[0]++; } else if (longestRun > V0 + K) { V[K]++; } else { V[longestRun - V0]++; } } //calculate p_value double chi_squared = 0.0; for (int i = 0; i <= K; i++) { chi_squared += ((V[i] - N * pi[i]) * (V[i] - N * pi[i])) / (N * pi[i]); } double p_value = Cephes.igamc((double)(K / 2.0), chi_squared / 2.0); if (printResults) { Report report = new Report("4: Test for the Longest Run of Ones in a Block"); report.Write("\t\t\t LONGEST RUNS OF ONES TEST\n"); report.Write("\t\t---------------------------------------------\n"); report.Write("\t\tCOMPUTATIONAL INFORMATION:\n"); report.Write("\t\t---------------------------------------------\n"); report.Write("\t\t(a) N (# of substrings) = "+ N); report.Write("\t\t(b) M (Substring Length) = " + M); report.Write("\t\t(c) Chi^2 = " + chi_squared); report.Write("\t\t---------------------------------------------\n"); report.Write("\t\t F R E Q U E N C Y\n"); report.Write("\t\t---------------------------------------------\n"); if (K == 3) { report.Write("\t\t <=1 2 3 >=4 P-value Assignment"); report.Write("\t\t "+V[0]+" "+V[1]+" "+V[2]+" "+V[3]); } else if (K == 5) { report.Write("\t\t<=4 5 6 7 8 >=9 P-value Assignment"); report.Write("\t\t "+V[0]+" "+V[1]+" "+V[2]+" "+V[3]+" "+V[4]+" "+V[5]); } else { report.Write("\t\t<=10 11 12 13 14 15 >=16 P-value Assignment"); report.Write("\t\t "+V[0]+" "+V[1]+" "+V[2]+" "+V[3]+" "+V[4]+" "+V[5]+" "+V[6]); } if (p_value < 0 || p_value > 1) { report.Write("WARNING: P_VALUE IS OUT OF RANGE.\n"); } report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS"+"{0}\t\tp_value = "+ p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { double[] pi = new double[6]; double lambda = (double)(M - B.Length + 1) / Math.Pow(2, B.Length); double eta = lambda / 2.0; double total = 0.0; for (int i = 0; i < K; i++) { //compute prior probabilities pi[i] = probability(i, eta); total += pi[i]; } pi[K] = 1 - total; int[] v = new int[K+1]; for (int i = 0; i < N; i++) { //search for a match of the template in each block int count = 0; for (int j = 0; j < M - B.Length + 1; j++) { bool match = true; for (int k = 0; k < B.Length; k++) { if (B[k] != model.epsilon[i * M + j + k]) { match = false; } } if (match) { count++; } } if (count < K) { //record the matches found v[count]++; } else { v[K]++; } } //compute p_value double sum = 0.0; double chiSquared = 0.0; for (int i = 0; i < K + 1; i++) { chiSquared += Math.Pow((double)v[i] - (double)N * pi[i], 2) / ((double)N * pi[i]); sum += v[i]; } double p_value = Cephes.igamc(5.0 / 2.0, chiSquared / 2.0); if (printResults) { Report report = new Report("8: Overlapping Template Matching Test"); report.Write("\t\t OVERLAPPING TEMPLATE OF ALL ONES TEST"); report.Write("\t\t-----------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t-----------------------------------------------"); report.Write("\t\t(a) n (sequence_length) = " + n); report.Write("\t\t(b) m (block length of 1s) = " + B.Length); report.Write("\t\t(c) M (length of substring) = " + M); report.Write("\t\t(d) N (number of substrings) = " + N); report.Write("\t\t(e) lambda [(M-m+1)/2^m] = " + lambda); report.Write("\t\t(f) eta = " + eta); report.Write("\t\t(g) Chi^2 = " + chiSquared); report.Write("\t\t(h) P-value = " + p_value); report.Write("\t\t-----------------------------------------------"); report.Write("\t\t F R E Q U E N C Y"); report.Write("\t\t", false); for (int i = 0; i < K; i++) { report.Write(" " + i + " "); } report.Write(" >=" + K); report.Write("\t\t-----------------------------------------------"); report.Write("\t\t", false); for (int i = 0; i < K + 1; i++) { report.Write(" " + v[i] + " "); } if (p_value < 0 || p_value > 1) { report.Write("WARNING: P_VALUE IS OUT OF RANGE."); } report.Write(p_value+" "+(p_value < ALPHA ? "FAILURE" : "SUCCESS")); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public unsafe override double[] run(bool printResults) { double[] X = new double[n]; for (int i = 0; i < n; i++) { X[i] = 2 * (int)model.epsilon[i] - 1; //map all bits in binary string (0->-1,1->1) } double[] m = new double[n / 2 + 1]; //generate DFT of the binary string, using the unsafe functions implemented in C fixed (double* wsavePtr = &(new double[2 * n])[0]) { fixed (int* ifacPtr = &(new int[15])[0]) { fixed (double* mPtr = &m[0]) { fixed (double* XPtr = &X[0]) { FFT.__ogg_fdrffti(n, wsavePtr, ifacPtr); //init stage for work arrays FFT.__ogg_fdrfftf(n, XPtr, wsavePtr, ifacPtr); //apply FFT on data } } } } //get magnitude of the DFT produced (to convert complex domain to real domain) m[0] = Math.Sqrt(X[0] * X[0]); for (int i = 0; i < n / 2; i++) { if (2 * i + 2 >= X.Length) { m[i + 1] = Math.Sqrt(Math.Pow(X[2 * i + 1], 2)); } else { m[i + 1] = Math.Sqrt(Math.Pow(X[2 * i + 1], 2) + Math.Pow(X[2 * i + 2], 2)); } } int N_l = 0; double T = Math.Sqrt(2.995732274*n); //calculate upper bound (T) (the 95% peak height threshold) for (int i = 0; i < n / 2; i++) { if (m[i] < T) { N_l++; //count observed number of peaks in |DFT| greater than T } } double N_0 = 0.95 * n / 2.0; //expected number of peaks double d = (N_l - N_0) / Math.Sqrt(n / 4.0 * 0.95 * 0.05); //calculate p_value double p_value = Cephes.erfc(Math.Abs(d) / Math.Sqrt(2.0)); if (printResults) { Report report = new Report("6: Discrete Fourier Transform (Sprectral) Test"); report.Write("\t\t\t\tFFT TEST"); report.Write("\t\t-------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t-------------------------------------------"); report.Write("\t\t(-) Upper Bound= " + T); report.Write("\t\t(b) N_l = " + N_l); report.Write("\t\t(c) N_o = " + N_0); report.Write("\t\t(d) d = " + d); report.Write("\t\t-------------------------------------------"); report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value = " + p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { double[] Pm = new double[3]; int r = Math.Min(M, Q); //compute predicted probabilities double product = 1; for (int i = 0; i <= r - 1; i++) { product *= ((1.0 - Math.Pow(2, i - Q)) * (1.0 - Math.Pow(2, i - M))) / (1.0 - Math.Pow(2, i - r)); } Pm[0] = Math.Pow(2, r * (M + Q - r) - M * Q) * product; r--; product = 1; for (int i = 0; i <= r - 1; i++) { product *= ((1.0 - Math.Pow(2, i - Q)) * (1.0 - Math.Pow(2, i - M))) / (1.0 - Math.Pow(2, i - r)); } Pm[1] = Math.Pow(2, r * (M + Q - r) - M * Q) * product; Pm[2] = 1 - (Pm[0] + Pm[1]); int N = n / (M * Q); //number of blocks int[] Fm = new int[3]; for (int k = 0; k < N; k++) { //construct the matrix of MxQ in size int[,] matrix = new int[M, Q]; for (int i = 0; i < M; i++) { for (int j = 0; j < Q; j++) { matrix[i,j] = model.epsilon[k * (M * Q) + j + i * M]; } } int R = computeRank(M, Q, matrix); //get the rank of the matrix if (R == M) { Fm[0]++; //full rank } else if (R == M - 1) { Fm[1]++; //full rank - 1 } } Fm[2] = N - (Fm[0] + Fm[1]); //full rank - 2 //compute p_value double chi_squared = (Math.Pow(Fm[0] - N * Pm[0], 2) / (double)(N * Pm[0]) + Math.Pow(Fm[1] - N * Pm[1], 2) / (double)(N * Pm[1]) + Math.Pow(Fm[2] - N * Pm[2], 2) / (double)(N * Pm[2])); double p_value = Cephes.igamc(1, chi_squared / 2.0); if (printResults) { Report report = new Report("2.5 Binary Matrix Rank Test"); report.Write("\t\t\t\tRANK TEST"); report.Write("\t\t---------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t---------------------------------------------"); report.Write("\t\t(a) Probability P_"+M+" = " + Pm[0]); report.Write("\t\t(b) P_"+(M - 1)+" = " + Pm[1]); report.Write("\t\t(c) P_"+(M - 2)+" = " + Pm[2]); report.Write("\t\t(d) Frequency F_"+M+" = " + Fm[0]); report.Write("\t\t(e) F_"+(M - 1)+" = "+ Fm[1]); report.Write("\t\t(f) F_"+(M - 2)+" = " + Fm[2]); report.Write("\t\t(g) # of matrices = " + N); report.Write("\t\t(h) Chi^2 = "+chi_squared); report.Write("\t\t(i) NOTE: "+n % (M * Q)+" BITS WERE DISCARDED."); report.Write("\t\t---------------------------------------------"); report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS"+"\t\tp_value = "+p_value); if (p_value < 0 || p_value > 1) { report.Write("WARNING: P_VALUE IS OUT OF RANGE."); } model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { double[] expected_value = { 0, 0, 0, 0, 0, 0, 5.2177052, 6.1962507, 7.1836656, 8.1764248, 9.1723243, 10.170032, 11.168765, 12.168070, 13.167693, 14.167488, 15.167379 }; double[] variance = { 0, 0, 0, 0, 0, 0, 2.954, 3.125, 3.238, 3.311, 3.356, 3.384, 3.401, 3.410, 3.416, 3.419, 3.421 }; int K = (int) (n/L - (double)Q); //number of test blocks int p = (int)Math.Pow(2, L); long[] T = new long[p]; //initialization segment for (int i = 1; i <= Q; i++) { long decValue = 0; for (int j = 0; j < L; j++) { decValue += model.epsilon[(i - 1) * L + j] * (long)Math.Pow(2, L - 1 - j); //calculate decimal value of segment } T[decValue] = i; } //test segment double sum = 0; for ( int i=Q+1; i<=Q+K; i++ ) { long decValue = 0; for (int j = 0; j < L; j++) { decValue += model.epsilon[(i - 1) * L + j] * (long)Math.Pow(2, L - 1 - j); //calculate decimal value of segment } sum += Math.Log(i - T[decValue])/Math.Log(2); T[decValue] = i; } double phi = (double)(sum / (double)K); //forumla from 2.9.4(5) double c = 0.7 - 0.8 / (double)L + (4 + 32 / (double)L) * Math.Pow(K, -3 / (double)L) / 15; double sigma = c * Math.Sqrt(variance[L] / (double)K); //calculate p_value double arg = Math.Abs(phi-expected_value[L])/(Math.Sqrt(2) * sigma); double p_value = Cephes.erfc(arg); if (printResults) { Report report = new Report("9: Maurer’s “Universal Statistical” Test"); report.Write("\t\tUNIVERSAL STATISTICAL TEST"); report.Write("\t\t--------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t--------------------------------------------"); report.Write("\t\t(a) L = "+ L); report.Write("\t\t(b) Q = " + Q); report.Write("\t\t(c) K = " + K); report.Write("\t\t(d) sum = " + sum); report.Write("\t\t(f) variance = " + variance[L]); report.Write("\t\t(g) exp_value = " + expected_value[L]); report.Write("\t\t(h) phi = " + phi); report.Write("\t\t(i) WARNING: "+(n - (Q + K) * L)+" bits were discarded."); report.Write("\t\t-----------------------------------------"); if (p_value < 0 || p_value > 1) { report.Write("\t\tWARNING: P_VALUE IS OUT OF RANGE"); } report.Write((p_value < ALPHA ? "FAILURE" : "SUCCESS")+"\t\tp_value = "+p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Runs the test /// </summary> /// <param name="printResults">If true text output will be added to a log, otherwise not</param> /// <returns>The p_value(s) of the test based upon the input data</returns> public override double[] run(bool printResults) { int S = 0; int sup = 0; int inf = 0; int z = 0; for (int k = 0; k < n; k++) { //calculate the partial sum if (model.epsilon[k] == 1) { S++; } else { S--; } if (S > sup) { sup++; } if (S < inf) { inf--; } //compute the test statistic if (mode) { z = (sup > -inf) ? sup : -inf; } else { z = (sup - S > S - inf) ? sup - S : S - inf; } } //compute p_value double sum1 = 0.0; for (int k = (-n / z + 1) / 4; k <= (n / z - 1) / 4; k++) { sum1 += Cephes.normal(((4 * k + 1) * z) / Math.Sqrt(n)); sum1 -= Cephes.normal(((4 * k - 1) * z) / Math.Sqrt(n)); } double sum2 = 0.0; for (int k = (-n / z - 3) / 4; k <= (n / z - 1) / 4; k++) { sum2 += Cephes.normal(((4 * k + 3) * z) / Math.Sqrt(n)); sum2 -= Cephes.normal(((4 * k + 1) * z) / Math.Sqrt(n)); } double p_value = 1.0 - sum1 + sum2; if (printResults) { Report report = new Report("13: Cumulative Sums (Cusum) Test"); report.Write("\t\t CUMULATIVE SUMS (" + (mode ? "FORWARD" : "REVERSE") + ") TEST"); report.Write("\t\t-------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t-------------------------------------------"); report.Write("\t\t(a) The maximum partial sum = "+ z); report.Write("\t\t-------------------------------------------"); if (p_value < 0 || p_value > 1) { report.Write("\t\tWARNING: P_VALUE IS OUT OF RANGE"); } report.Write((p_value < ALPHA ? "FAILURE" : "SUCCESS")+"\t\tp_value = "+p_value); model.reports.Add(report.title, report); } return new double[] { p_value }; }
/// <summary> /// Method for running tests selected in the view /// </summary> /// <remarks> /// Gets data from the view object, such as file for binary string file, and which tests to run with which data /// </remarks> internal void runTests() { Model model = new Model(Util.str2ints(Util.loadData(view.getFilePath()), view.getSplitStr())); List<Test> tests = new List<Test>(); if (view.performFrequencyTest()) { tests.Add(new Frequency(view.getFrequency_n(), ref model)); } if (view.performBlockFrequencyTest()) { tests.Add(new BlockFrequency(view.getBlockFrequency_M(), view.getBlockFrequency_n(), ref model)); } if (view.performRunsTest()) { tests.Add(new Runs(view.getRuns_n(), ref model)); } if (view.performLongestRunOfOnesTest()) { tests.Add(new LongestRunOfOnes(view.getLongestRunOfOnes_n(), ref model)); } if (view.performMatrixRankTest()) { tests.Add(new Rank(view.getMatrixRank_n(), ref model)); } if (view.performDiscreteFourierTransformTest()) { tests.Add(new DiscreteFourierTransform(view.getDiscreteFourierTransform_n(), ref model)); } if (view.performNonOverlappingTemplateMatchingTest()) { if (view.performSingleNonOverlappingTemplateMatchingTest()) { tests.Add(new NonOverlappingTemplateMatching(view.getNonOverlappingTemplateMatching_B(), view.getNonOverlappingTemplateMatching_n(), ref model)); } else { tests.Add(new NonOverlappingTemplateMatching(view.getNonOverlappingTemplateMatching_m(), view.getNonOverlappingTemplateMatching_n(), ref model)); } } if (view.performOverlappingTemplateMatchingTest()) { tests.Add(new OverlappingTemplateMatching(view.getOverlappingTemplateMatching_B(), view.getOverlappingTemplateMatching_n(), ref model)); } if (view.performUniversalTest()) { if (view.performCustomUniversalTest()) { tests.Add(new Universal(view.getUniversal_L(), view.getUniversal_Q(), view.getUniversal_n(), ref model)); } else { tests.Add(new Universal(view.getUniversal_n(), ref model)); } } if (view.performLinearComplexityTest()) { tests.Add(new LinearComplexity(view.getLinearComplexity_M(), view.getLinearComplexity_n(), ref model)); } if (view.performSerialTest()) { tests.Add(new Serial(view.getSerial_m(), view.getSerial_n(), ref model)); } if (view.performApproximateEntropyTest()) { tests.Add(new ApproximateEntropy(view.getApproximateEntropy_m(), view.getApproximateEntropy_n(), ref model)); } if (view.performCumulativeSumsTest()) { tests.Add(new CumulativeSums(view.performForwardCumulativeSumsTest(), view.getCumulativeSums_n(), ref model)); } if (view.performRandomExcursionsTest()) { tests.Add(new RandomExcursions(view.getRandomExcursions_n(), ref model)); } if (view.performRandomExcursionsVariantTest()) { tests.Add(new RandomExcursionsVariant(view.getRandomExcursionsVariant_n(), ref model)); } view.showProgressBar(); view.updateProgressBar(10); Report full = new Report("All Tests"); foreach (Test t in tests) { t.run(true); view.updateProgressBar(90 / tests.Count); full.Write(model.reports.Last().Value.body); } model.reports.Add(full.title, full); new ReportsForm(model.reports).Show(); view.hideProgressBar(); }