/// <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 });
        }
Example #2
0
        /// <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)
        {
            //calculate all psi_squares
            double psim0 = this.psi2(this.m, this.n);
            double psim1 = this.psi2(this.m - 1, this.n);
            double psim2 = this.psi2(this.m - 2, this.n);
            double del1  = psim0 - psim1;
            double del2  = psim0 - 2.0 * psim1 + psim2;

            //calculate p_values
            double p_value1 = Cephes.igamc(Math.Pow(2, this.m - 1) / 2, del1 / 2.0);
            double p_value2 = Cephes.igamc(Math.Pow(2, this.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) = " + this.m);
                report.Write("\t\t(b) Sequence length (n) = " + this.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);
                this.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 });
            }
        }
Example #5
0
        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 });
        }
Example #6
0
        /// <summary>
        /// Returns a probability based on those given in 3.8
        /// </summary>
        /// <param name="u"></param>
        /// <param name="eta"></param>
        /// <returns></returns>
        private double probability(int u, double eta)
        {
            int    l;
            double sum, p;

            if (u == 0)
            {
                p = Math.Exp(-eta);
            }
            else
            {
                sum = 0.0;
                for (l = 1; l <= u; l++)
                {
                    sum += Math.Exp(-eta - u * Math.Log(2) + l * Math.Log(eta) - Cephes.lgam(l + 1) + Cephes.lgam(u) - Cephes.lgam(l) - Cephes.lgam(u - l + 1));
                }
                p = sum;
            }
            return(p);
        }
Example #7
0
        /// <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 });
        }
Example #8
0
        /// <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 - this.B.Length + 1) / Math.Pow(2, this.B.Length);
            double   eta    = lambda / 2.0;
            double   total  = 0.0;

            for (int i = 0; i < K; i++)
            { //compute prior probabilities
                pi[i]  = this.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 - this.B.Length + 1; j++)
                {
                    bool match = true;
                    for (int k = 0; k < this.B.Length; k++)
                    {
                        if (this.B[k] != this.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)      = " + this.n);
                report.Write("\t\t(b) m (block length of 1s)   = " + this.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"));
                this.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[] 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 });
        }
Example #11
0
        /// <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>
        /// 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 });
        }
Example #13
0
        /// <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)
        {
            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)
        {
            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[this.n];
            //compute partial sums
            S[0] = 2 * (int)this.model.epsilon[0] - 1;
            for (int i = 1; i < this.n; i++)
            {
                S[i] = S[i - 1] + 2 * this.model.epsilon[i] - 1;
                if (S[i] == 0)
                {
                    J++;
                }
            }
            if (S[this.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)  = " + this.n);
            }

            double[] p_values   = new double[18];
            int      constraint = (int)Math.Max(0.005 * Math.Pow(this.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 < this.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)
            {
                this.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[] 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);
        }