Example #1
0
        /// <summary>
        /// 計算穩定狀態下的參數組(單一觀測值),使用一般的 Variance-Covariance Matrix 去計算,而非 Sullivan-Woodall
        /// </summary>
        /// <param name="data">欲使用的資料表</param>
        /// <returns></returns>
        public TsquareParameters Execute(Algebra.Matrix <double> data, Mtb.Project proj)
        {
            //確認基本資訊能否計算
            int p = data.ColumnCount;
            int m = data.RowCount;

            if (m - p <= 0)
            {
                throw new Exception(string.Format("樣本數不可低於{0},請重新確認。", p));
            }

            //組合管制界線指令並計算 Phase1 的 limit
            double        ucl;
            StringBuilder cmnd = new StringBuilder();

            cmnd.AppendLine("invCdf 0.9973 k1;");
            cmnd.AppendFormat("Beta {0} {1}.\r\n", (double)p / 2, (double)(m - p - 1) / 2);
            cmnd.AppendFormat("let k1=(({0}-1)**2)/{0}*k1\r\n", m);
            try
            {
                Mtb.Worksheet ws    = proj.Worksheets.Add(1);
                string        fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString());
                proj.ExecuteCommand(string.Format("Exec \"{0}\" 1", fpath), ws);
                ucl = ws.Constants.Item("k1").GetData();
                ws.Delete();
                proj.Commands.Delete();
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }


            double miss = Mtblib.Tools.MtbTools.MISSINGVALUE;
            var    M    = Algebra.Matrix <double> .Build;

            //計算 Mean vector & Covariance matrix
            IEnumerable <Algebra.Vector <double> > cols = data.EnumerateColumns();
            var mean    = M.DenseOfColumnMajor(1, data.ColumnCount, cols.Select(x => x.Where(o => o < miss).Average()));
            var subData = M.DenseOfRows((data.EnumerateRows().Where(x => x.All(y => y < miss)).ToArray()));
            var diff    = subData - M.Dense(subData.RowCount, 1, (i, j) => 1).Multiply(mean);
            var cov     = diff.Transpose().Multiply(diff) / (subData.RowCount - 1);
            var invS    = cov.Inverse();

            TsquareParameters tsquarePara = new TsquareParameters()
            {
                Mean         = mean,
                Covariance   = cov,
                SampleSize   = m,
                SubgroupSize = 1
            };

            //計算出資料的Tsquare value
            List <double> t2 = new List <double>();

            for (int i = 0; i < data.RowCount; i++)
            {
                if (data.Row(i).ToArray().All(x => x < miss))
                {
                    t2.Add(Tool.CalculateTSquare(data.Row(i).ToRowMatrix(), mean, invS));
                }
                else
                {
                    t2.Add(miss);
                }
            }

            if (t2.Any(x => x >= ucl && x < miss))
            {
                int[] oocRow = t2.Select((x, i) => new { Tsquare = x, Index = i }).Where(x => x.Tsquare >= ucl && x.Tsquare < miss).Select(x => x.Index).OrderByDescending(x => x).ToArray();
                subData = data.Clone();
                //逐列移除OOC的資料列
                for (int i = 0; i < oocRow.Length; i++)
                {
                    subData = subData.RemoveRow(oocRow[i]);
                }
                tsquarePara = Execute(subData, proj);
            }

            return(tsquarePara);
        }
        /// <summary>
        /// 判斷individaul T2管制圖的參數是否合法? 如果合法不回發生任何事,若不合法則回傳例外。
        /// </summary>
        /// <param name="paraSet"></param>
        /// <returns></returns>
        private void ParaValidation(ParaSetInfo paraSet)
        {
            DataTable mean = paraSet.Mean;
            DataTable cov  = paraSet.Cov;
            int?      ssiz = paraSet.SampleSize;

            if (mean == null || cov == null)
            {
                throw new ArgumentNullException("尚未輸入平均數向量或共變異數矩陣");
            }
            if (SampleSize == null || SampleSize <= 0)
            {
                throw new Exception("樣本數內容不正確");
            }

            //確認輸入的數據是否正確(數量、共變異矩陣對稱、對角項大於0、正定等特性)
            int    r = cov.Columns.Count;
            int    c = cov.Rows.Count;
            double result;

            if (mean.Rows.Cast <DataRow>().Any(x => x.ItemArray.Any(y => !Double.TryParse(y.ToString(), out result))))
            {
                throw new Exception("平均數欄位內容必須為數字");
            }
            if (cov.Rows.Cast <DataRow>().Any(x => x.ItemArray.Any(y => !Double.TryParse(y.ToString(), out result))))
            {
                throw new Exception("共變異數內容必須為數字");
            }

            //將共變異數矩陣轉到Minitab中判斷是否合法
            double[] covArray = new double[r * c];

            for (int cCnt = 0; cCnt < c; cCnt++)
            {
                for (int rCnt = cCnt; rCnt < r; rCnt++)
                {
                    if (rCnt == cCnt)
                    {
                        double value = double.Parse(cov.Rows[rCnt][cCnt].ToString());
                        if (value <= 0)
                        {
                            throw new Exception("共變異數矩陣對角項小於等於0");
                        }
                        covArray[cCnt * r + rCnt] = value;
                    }
                    else
                    {
                        if (cov.Rows[rCnt][cCnt].ToString() != cov.Rows[cCnt][rCnt].ToString())
                        {
                            throw new Exception("共變異數矩陣不對稱");
                        }
                        double value = double.Parse(CovarianceMatrix.Rows[rCnt][cCnt].ToString());
                        covArray[cCnt * r + rCnt] = value;
                        covArray[rCnt * r + cCnt] = value;
                    }
                }
            }
            Mtb.Worksheet ws  = Project.Worksheets.Add(1);
            Mtb.Matrix    mat = ws.Matrices.Add(Quantity: 1);
            Mtb.Column    col = ws.Columns.Add(Quantity: 1);
            mat.SetData(covArray, 1, 1);
            Project.ExecuteCommand(string.Format("Eigen {0} {1}.\r\n", mat.SynthesizedName, col.SynthesizedName), ws);
            double[] eigvalue = col.GetData();
            if (eigvalue.Any(x => x <= 0))
            {
                throw new Exception("共變異數矩陣不為正定");
            }
            ws.Delete();
            Project.Commands.Delete();
        }