/// <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(); }