public static string DataConverterRtoCS(CATItems itemBank, Double[] items) { int index = 0; try { // Populate data to the object array property "all_items_poly" for (int i = 0; i < itemBank.colSize; i++) { double[] array = new double[itemBank.NumOfItems]; for (int j = 0; j < itemBank.NumOfItems; j++) { array[j] = items[index]; index++; } itemBank.all_items_poly[i] = array; } // Convert "NA" values to "NaN" itemBank.NAValueHandler(); } catch (System.IndexOutOfRangeException ex) { //throw ex; } return("Index value: " + index.ToString()); //return itemBank; }
private void ProcessTheta(int[] items, int[] responses) { CATItems itemBank = null; if ((bool)Session["IsDicho"]) { itemBank = new CATItems(items.Length); Tuple <CATItems.ColumnNames, int>[] cols = itemBank.GetKeys(); for (int i = 0; i < cols.Length; i++) { string tempKey = cols[i].Item1.ToString() + cols[i].Item2.ToString(); itemBank.SetItemParamter(cols[i], cat_items[tempKey].Select(y => (double)y).ToArray()); } // Calculate theta CalculateTheta(itemBank, responses); } if ((bool)Session["IsPoly"]) { ModelNames.Models paramModel = ModelNames.Models.GRM; itemBank = new CATItems(items.Length, paramModel.EnumToString(), nrCat: 5); Tuple <CATItems.ColumnNames, int>[] cols = itemBank.GetKeys(); for (int i = 0; i < cols.Length; i++) { string tempKey = cols[i].Item1.ToString() + cols[i].Item2.ToString(); itemBank.SetItemParamter(cols[i], cat_items[tempKey].Select(y => (double)y).ToArray()); } // Calculate theta CalculateTheta(itemBank, responses, model: paramModel.EnumToString()); } }
public void test_NextItem_P(int numofItems, ModelNames.Models paramModel, ModelNames.CriterionTypes paramCriterion) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Polytomous Items CharacterVector modelName = engineObj.CreateCharacterVector(new string[] { paramModel.EnumToString() }); engineObj.SetSymbol("modelName", modelName); DataFrame PolyItems = engineObj.Evaluate("PolyItems <- genPolyMatrix(" + numofItems + ", 5, model = modelName, same.nrCat = TRUE)").AsDataFrame(); engineObj.SetSymbol("PolyItems", PolyItems); // Adapting with the existing "CAT-Items" type (Wrapper) Console.WriteLine("*******************************************"); Console.WriteLine("Polytomous Items, Model : " + paramModel.EnumToString()); Console.WriteLine("*******************************************"); CATItems itemBank = new CATItems(PolyItems[0].Length, paramModel.EnumToString(), 5); Tuple <CATItems.ColumnNames, int>[] cols = itemBank.GetKeys(); for (int i = 0; i < cols.Length; i++) { itemBank.SetItemParamter(cols[i], PolyItems[i].Select(y => (double)y).ToArray()); } // Call "NextItem" function from R GenericVector r_NextItem = engineObj.Evaluate("r_NextItem <- nextItem(PolyItems, model = modelName, theta = 0, criterion = \"" + paramCriterion.ToString() + "\")").AsList(); // Selected item NumericVector item = r_NextItem[0].AsNumeric(); DataFrame par = r_NextItem[1].AsDataFrame(); // Value of "info" NumericVector thStart = r_NextItem[2].AsNumeric(); // Criterion CharacterVector startSelect = r_NextItem[3].AsCharacter(); // Call "NextItem" function from CS NextItemModel cs_NextItem = CatRLib.NextItem(itemBank, model: paramModel.EnumToString(), theta: 0, criterion: (int)paramCriterion); //Test passed for "MFI" if (item[0] != cs_NextItem.item) { resultFlag = false; } Assert.IsTrue(resultFlag); }
public void testKL_D(int NumOfItems) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Dichotomous Items DataFrame DichoItems = engineObj.Evaluate("DichoItems <- genDichoMatrix(items = " + NumOfItems + ")").AsDataFrame(); engineObj.SetSymbol("DichoItems", DichoItems); // Adapting with the existing "CAT-Items" type (Wrapper) CATItems itemBank = new CATItems(DichoItems[0].Length, false); // New Dictionary itemBank.SetItemParamter(CATItems.ColumnNames.a, DichoItems[0].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.b, DichoItems[1].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.c, DichoItems[2].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.d, DichoItems[3].Select(y => (double)y).ToArray()); // Dichotomous Items DataFrame it_given_R = engineObj.Evaluate("it_given_R <- DichoItems[c(4, 8),]").AsDataFrame(); engineObj.SetSymbol("it_given_R", it_given_R); CATItems it_given = itemBank.FindItem(new int[] { 4, 8 }); //Creation of a response pattern NumericVector x_val = engineObj.Evaluate("x_val <- c(0, 1)").AsNumeric(); engineObj.SetSymbol("x_val", x_val); int[] x = new int[] { 0, 1 }; // Call "thetaEST" function from R, method = \"ML\" NumericVector Theta = engineObj.Evaluate("Theta <- thetaEst(it_given_R, x_val, method = \"ML\")").AsNumeric(); // Call "KL" function from R NumericVector r_KL = engineObj.Evaluate("r_KL <- KL(DichoItems, 1, x_val, it_given_R, theta = Theta)").AsNumeric(); // Call "thetaEST" function from CS double th = CatRLib.ThetaEst(it_given, x, "", method: "ML"); // Call "KL" function from CS double cs_KL = CatRLib.KL(itemBank, 1, x, it_given, "", theta: th); if (r_KL[0] - cs_KL > testEpsilon) { resultFlag = false; } Assert.IsTrue(resultFlag); }
public static NextItemModel NextItem(CATItems itemBank, string model = null, double theta = 0, int[] Out = null, int[] x = null, int criterion = 5, /* MFI */ string method = "BM", string priorDist = "norm", double[] priorPar = null, double D = 1, double[] range = null, int[] parInt = null, int infoType = 2, /* observed */ int randomesque = 1, int rule = 1, /* Length */ double thr = 20, double?SETH = null, double AP = 1, int[] nAvailable = null, int maxItems = 50, CBControlList cbControl = null, string[] cbGroup = null) { NextItemModel result = CatRcs.NextItem.NextItem_Calc(itemBank, model, theta, Out, x, criterion, method, priorDist, priorPar, D, range, parInt, infoType, randomesque, rule, thr, SETH, AP, nAvailable, maxItems, cbControl, cbGroup); return(result); }
// Pi method for Dichotomous items public static PiList Pi_Calc(double th, CATItems it, string model, double D) { PiList objPi = null; if (String.IsNullOrEmpty(model)) { #region "Functional Logic" try { double[] e = new double[it.NumOfItems]; objPi = new PiList(it.NumOfItems); for (int i = 0; i < it.NumOfItems; i++) { e[i] = Math.Exp(D * it.a[i] * (th - it.b[i])); // round test double final_pi = 0; double temp_pi = it.c[i] + (it.d[i] - it.c[i]) * e[i] / (1 + e[i]); final_pi = (temp_pi == 0) ? 1e-10 : temp_pi; final_pi = (temp_pi == 1) ? 1 - 1e-10 : temp_pi; double temp_dPi = D * it.a[i] * e[i] * (it.d[i] - it.c[i]) / Math.Pow(1 + e[i], 2); // round test double temp_d2Pi = Math.Pow(D, 2) * Math.Pow(it.a[i], 2) * e[i] * (1 - e[i]) * (it.d[i] - it.c[i]) / Math.Pow(1 + e[i], 3); // round test double temp_d3Pi = Math.Pow(D, 3) * Math.Pow(it.a[i], 3) * e[i] * (it.d[i] - it.c[i]) * (Math.Pow(e[i], 2) - 4 * e[i] + 1) / Math.Pow(1 + e[i], 4); // round test objPi.AddPiList(final_pi, temp_dPi, temp_d2Pi, temp_d3Pi, i); } } catch (Exception ex) { if (ex != null) { if (objPi == null) { objPi = new PiList(ex.Message); } } return(objPi); } #endregion } else { objPi = new PiList(); objPi.Errors.SetValue("Model is not empty!!", 0); } return(objPi); }
public void test_MWI_D(int NumOfItems) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Dichotomous Items DataFrame DichoItems = engineObj.Evaluate("DichoItems <- genDichoMatrix(items = " + NumOfItems + ")").AsDataFrame(); engineObj.SetSymbol("DichoItems", DichoItems); // Adapting with the existing "CAT-Items" type (Wrapper) CATItems itemBank = new CATItems(DichoItems[0].Length, false); // New Dictionary itemBank.SetItemParamter(CATItems.ColumnNames.a, DichoItems[0].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.b, DichoItems[1].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.c, DichoItems[2].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.d, DichoItems[3].Select(y => (double)y).ToArray()); // Dichotomous Items DataFrame it_given_R = engineObj.Evaluate("it_given_R <- DichoItems[c(4, 8),]").AsDataFrame(); engineObj.SetSymbol("it_given_R", it_given_R); //Creation of a response pattern for theta value engineObj.Evaluate("set.seed(1)"); NumericVector x_val = engineObj.Evaluate("x_val <- genPattern(0, it_given_R)").AsNumeric(); engineObj.SetSymbol("x_val", x_val); int[] x = x_val.Select(y => (int)y).ToArray(); CATItems it_given = itemBank.FindItem(new int[] { 4, 8 }); // Call "MWI" function from R NumericVector r_mwi = engineObj.Evaluate("r_mei <- MWI(DichoItems, 1, x_val, it_given_R, type = \"MPWI\")").AsNumeric(); // Call "MWI" function from CatRCS double cs_mwi = CatRLib.MWI(itemBank, 1, x, it_given, "", 2); if (r_mwi[0] - cs_mwi > testEpsilon) { resultFlag = false; } Assert.IsTrue(resultFlag); }
public static CATItems DataConverterRtoCS(CATItems itemBank, DataFrame items) { // Populate data to the object array property "all_items_poly" for (int i = 0; i < itemBank.colSize; i++) { itemBank.all_items_poly[i] = items[i].Select(y => (double)y).ToArray(); } // Convert "NA" values to "NaN" itemBank.NAValueHandler(); return(itemBank); }
private void CalculateTheta(CATItems itemBank, int[] responses, string model = "") { if (string.IsNullOrEmpty(model)) { // Calling "thetaEST" function double cs_ThetaEst = CatRcs.CatRLib.ThetaEst(itemBank, responses, ""); Session["Theta_Value"] = cs_ThetaEst; } else { double[] priorPar = new double[2]; priorPar[0] = -2; priorPar[1] = 2; // Calling "thetaEST" function double cs_ThetaEst = CatRcs.CatRLib.ThetaEst(it: itemBank, x: responses, method: "BM", model: model, priorPar: priorPar, priorDist: "Jeffreys"); Session["Theta_Value"] = cs_ThetaEst; } }
// Function for calculating Next Item public static NextItemModel NextItem_Calc(CATItems itemBank, string model = null, double theta = 0, int[] Out = null, int[] x = null, int criterion = 5, /* MFI */ string method = "BM", string priorDist = "norm", double[] priorPar = null, double D = 1, double[] range = null, int[] parInt = null, int infoType = 2, /* observed */ int randomesque = 1, int rule = 1, /* Length */ double thr = 20, double?SETH = null, double AP = 1, int[] nAvailable = null, int maxItems = 50, CBControlList cbControl = null, string[] cbGroup = null) { CATItems par = null; NextItemModel result = null; #region "Parameter Validation" if (priorPar == null || priorPar.Length < 2) { priorPar = new double[2]; priorPar[0] = 0; priorPar[1] = 1; } if (range == null || range.Length < 2) { range = new double[2]; range[0] = -4; range[1] = 4; } if (parInt == null || parInt.Length < 3) { parInt = new int[3]; parInt[0] = -4; parInt[1] = 4; parInt[2] = 33; } ModelNames.CriterionTypes?crit = null; switch (criterion) { case (int)ModelNames.CriterionTypes.bOpt: crit = ModelNames.CriterionTypes.bOpt; break; case (int)ModelNames.CriterionTypes.thOpt: crit = ModelNames.CriterionTypes.thOpt; break; case (int)ModelNames.CriterionTypes.KL: crit = ModelNames.CriterionTypes.KL; break; case (int)ModelNames.CriterionTypes.KLP: crit = ModelNames.CriterionTypes.KLP; break; case (int)ModelNames.CriterionTypes.MEI: crit = ModelNames.CriterionTypes.MEI; break; case (int)ModelNames.CriterionTypes.MEPV: crit = ModelNames.CriterionTypes.MEPV; break; case (int)ModelNames.CriterionTypes.MFI: crit = ModelNames.CriterionTypes.MFI; break; case (int)ModelNames.CriterionTypes.MLWI: crit = ModelNames.CriterionTypes.MLWI; break; case (int)ModelNames.CriterionTypes.MPWI: crit = ModelNames.CriterionTypes.MPWI; break; case (int)ModelNames.CriterionTypes.progressive: crit = ModelNames.CriterionTypes.progressive; break; case (int)ModelNames.CriterionTypes.proportional: crit = ModelNames.CriterionTypes.proportional; break; case (int)ModelNames.CriterionTypes.random: crit = ModelNames.CriterionTypes.random; break; } if (crit == null) { result = new NextItemModel(true, "Invalid 'criterion' name!"); return(result); } int mod = 0; ModelNames.Models modelEnum = ModelNames.StringToEnum(model); if (!String.IsNullOrEmpty(model)) { switch (modelEnum) { case ModelNames.Models.GRM: mod = 1; break; case ModelNames.Models.MGRM: mod = 2; break; case ModelNames.Models.PCM: mod = 3; break; case ModelNames.Models.GPCM: mod = 4; break; case ModelNames.Models.RSM: mod = 5; break; case ModelNames.Models.NRM: mod = 6; break; } if (mod == 0) { result = new NextItemModel(true, "Invalid 'model' type!"); return(result); } } #endregion int[] OUT = null; double[] empProp = null; int nrGroup = 0; double[] thProp = null; #region Handling "cbControl" Parameter if (cbControl == null) { OUT = Out; } else { if (cbGroup == null) { result = new NextItemModel(true, "'cbGroup' argument must be provided for content balancing!"); return(result); } if (RowColumn.Sum(cbControl.Props) != 1) { double temp_sum = RowColumn.Sum(cbControl.Props); for (int i = 0; i < cbControl.Props.Length; i++) { cbControl.Props[i] = cbControl.Props[i] / temp_sum; } } nrGroup = cbControl.Names.Length; empProp = new double[nrGroup]; if (Out == null) { empProp = CatRcs.Utils.CommonHelper.Replicate(new double[] { 0 }, nrGroup); } else { string[] temp_grp = new string[Out.Length]; for (int i = 0; i < Out.Length; i++) { temp_grp[i] = cbGroup[Out[i]]; } for (int j = 0; j < nrGroup; j++) { string[] values = temp_grp.Where(m => m == cbControl.Names[j]).ToArray(); if (values != null && values.Length > 0) { empProp[j] = values.Length; } else { empProp[j] = 0; } } empProp = empProp.Select(n => n / CatRcs.Utils.RowColumn.Sum(empProp)).ToArray(); // Functional Testing needed !! } thProp = cbControl.Props; List <int> indGroup = new List <int>(); int selGroup = 0; // Array of Group Numbers ex: "1 2 3 4 5" for nrGroup = 5. int[] GrpIndValues = new int[nrGroup]; GrpIndValues = GrpIndValues.Select((a, i) => i + 1).ToArray(); if (empProp.Min() == 0) { for (int m = 0; m < empProp.Length; m++) { if (empProp[m] == 0) { indGroup.Add(GrpIndValues[m]); } } } else { double[] tempProp = thProp.Select((a, i) => a - empProp[i]).ToArray(); for (int n = 0; n < tempProp.Length; n++) { if (tempProp[n] == tempProp.Max()) { indGroup.Add(GrpIndValues[n]); } } } if (indGroup.Count == 1) { selGroup = indGroup[0]; } else { selGroup = CatRcs.Utils.RandomNumberHandler.Sample(indGroup.ToArray(), 1, false)[0]; } // Populating the OUT array string[] tempGrp = cbGroup.Where(c => c != cbControl.Names[selGroup]).ToArray(); OUT = tempGrp.Select((a, i) => i + 1).ToArray(); OUT = Out.Concat(OUT).ToArray(); OUT = CatRcs.Utils.CommonHelper.Unique(OUT); } #endregion #region Handling "nAvalilable Parameter" if (nAvailable != null) { List <int> ind_temp = new List <int>(); for (int k = 0; k < nAvailable.Length; k++) { if (nAvailable[k] == 0) { ind_temp.Add(k); } } OUT = OUT.Concat(ind_temp.ToArray()).ToArray(); OUT = CatRcs.Utils.CommonHelper.Unique(OUT); } #endregion int select = 0; #region Criterion Type "MFI" if (crit == ModelNames.CriterionTypes.MFI) { int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] info = Ii.Ii_Calc(theta, itemBank, model, D).Ii; double[] ranks = CatRcs.Utils.CommonHelper.Rank(info).Select(m => m).ToArray(); int nrIt = new int[] { randomesque, (int)CatRcs.Utils.RowColumn.Sum(items) }.Min(); List <double> tempRanks = new List <double>(); for (int j = 0; j < items.Length; j++) { if (items[j] == 1) { tempRanks.Add(ranks[j]); } } tempRanks = tempRanks.OrderByDescending(n => n).ToList(); double[] keepRank = tempRanks.GetRange(0, nrIt).ToArray(); List <int> keep = new List <int>(); if (ranks.Length == items.Length) { for (int m = 0; m < keepRank.Length; m++) { for (int n = 0; n < ranks.Length; n++) { if ((items[n] == 1) && (ranks[n] == keepRank[m])) { keep.Add(n + 1); } } } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), info[select - 1], criterion, randomesque); } #endregion #region Criterion Type "bOpt" if (crit == ModelNames.CriterionTypes.bOpt) { if (string.IsNullOrEmpty(model)) { int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] distance = itemBank.GetItemParamter(CATItems.ColumnNames.b).Select(a => Math.Abs(a - theta)).ToArray(); double[] ranks = CatRcs.Utils.CommonHelper.Rank(distance).Select(m => m).ToArray(); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { ranks[OUT[a] - 1] = -1; } } int nrIt = new int[] { randomesque, (int)CatRcs.Utils.RowColumn.Sum(items) }.Min(); List <double> tempRanks = new List <double>(); for (int j = 0; j < items.Length; j++) { if (items[j] == 1) { tempRanks.Add(ranks[j]); } } tempRanks = tempRanks.OrderBy(n => n).ToList(); double[] keepRank = tempRanks.GetRange(0, nrIt).ToArray(); keepRank = keepRank.Distinct().ToArray(); List <int> keep = new List <int>(); if (ranks.Length == items.Length) { for (int m = 0; m < keepRank.Length; m++) { for (int n = 0; n < ranks.Length; n++) { if ((items[n] == 1) && (ranks[n] == keepRank[m])) { keep.Add(n + 1); } } } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), distance[select - 1], criterion, randomesque); } else { result = new NextItemModel(true, "bOpt's rule cannot be considered with polytomous items!"); return(result); } } #endregion #region Criterion Type "MLWI" OR "MPWI" if (crit == ModelNames.CriterionTypes.MLWI || crit == ModelNames.CriterionTypes.MPWI) { if (Out != null) { if (Out.Length == 1) { par = itemBank.FindItem(Out[0]); } else { par = itemBank.FindItem(Out); } } else { result = new NextItemModel(true, "Out parameter can't be empty!"); return(result); } int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] likInfo = CatRcs.Utils.CommonHelper.Replicate(new double[] { 0 }, itemBank.NumOfItems); int mwiType = 0; if (criterion == (int)ModelNames.CriterionTypes.MLWI) { mwiType = (int)ModelNames.MWI_Type.MLWI; } if (criterion == (int)ModelNames.CriterionTypes.MPWI) { mwiType = (int)ModelNames.MWI_Type.MPWI; } if (x != null) { for (int j = 0; j < itemBank.NumOfItems; j++) { if (items[j] == 1) { likInfo[j] = MWI.MWI_Calc(itemBank, j + 1, x, par, model, mwiType, priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]); /* item number is always 1 greater than the index */ } } } int nrIt = new int[] { randomesque, (int)CatRcs.Utils.RowColumn.Sum(items) }.Min(); double likVal = likInfo.ToList().OrderByDescending(n => n).ToArray()[nrIt - 1]; // First value with index 0 List <int> keep = new List <int>(); for (int k = 0; k < items.Length; k++) { if (likInfo[k] >= likVal) { keep.Add(k + 1); // Converting from index to item number } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), likInfo[select - 1], criterion, randomesque); } #endregion #region Criterion Type "KL" OR "KLP" if (crit == ModelNames.CriterionTypes.KL || crit == ModelNames.CriterionTypes.KLP) { if (Out != null) { if (Out.Length == 1) { par = itemBank.FindItem(Out[0]); } else { par = itemBank.FindItem(Out); } } else { result = new NextItemModel(true, "Out parameter can't be empty!"); return(result); } int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] klValue = CatRcs.Utils.CommonHelper.Replicate(new double[] { 0 }, itemBank.NumOfItems); double[] X = CatRcs.Utils.CommonHelper.Sequence(parInt[0], parInt[1], parInt[2]); #region "Function 'L' " Func <double, int[], CATItems, double> L = (th, r, param) => { double res = 0; var temp_1 = Pi.Pi_Calc(th, param, model, D).Pi.Select((p, i) => Math.Pow(p, r[i])).ToArray(); var temp_2 = Pi.Pi_Calc(th, param, model, D).Pi.Select((p, i) => Math.Pow(1 - p, 1 - r[i])).ToArray(); if (temp_1.Length == temp_2.Length) { var temp_3 = temp_1.Select((p, i) => p * temp_2[i]).ToArray(); res = temp_3.Aggregate((acc, val) => acc * val); } return(res); }; #endregion #region "Function 'LL' " Func <double, int[], CATItems, double> LL = (th, r, param) => { double res = 0; if (param.NumOfItems == 0) { res = 1; } else { double[,] prob = Pi.Pi_Poly_Calc(th, param, model, D).Pi; for (int i = 0; i < r.Length; i++) { res = res * prob[i, r[i] + 1]; } } return(res); }; #endregion double[] LF = null; if (string.IsNullOrEmpty(model)) { LF = X.Select(p => L(p, x, par)).ToArray(); } else { LF = X.Select(p => LL(p, x, par)).ToArray(); } int kType = 0; if (criterion == (int)ModelNames.CriterionTypes.KL) { kType = (int)ModelNames.KLTypes.KL; } if (criterion == (int)ModelNames.CriterionTypes.KLP) { kType = (int)ModelNames.KLTypes.KLP; } for (int j = 0; j < itemBank.NumOfItems; j++) { if (items[j] == 1) { klValue[j] = KL.KL_Calc(itemBank, j + 1, x, par, model, theta, priorPar, X, LF, kType, D, priorDist, parInt[0], parInt[1], parInt[2]); /* item number is always 1 greater than the index */ } } int nrIt = new int[] { randomesque, (int)CatRcs.Utils.RowColumn.Sum(items) }.Min(); double klVal = klValue.ToList().OrderByDescending(n => n).ToArray()[nrIt - 1]; List <int> keep = new List <int>(); for (int k = 0; k < items.Length; k++) { if (klValue[k] >= klVal) { keep.Add(k + 1); } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), klValue[select - 1], criterion, randomesque); } #endregion #region Criterion Type "MEI" if (crit == ModelNames.CriterionTypes.MEI) { int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] infos = CatRcs.Utils.CommonHelper.Replicate(new double[] { 0 }, itemBank.NumOfItems); for (int j = 0; j < items.Length; j++) { if (items[j] > 0) { infos[j] = MEI.MEI_Calc(itemBank, j + 1, x, theta, itemBank.FindItem(Out), model, method, D, priorPar, priorDist, range, parInt, infoType); } } int nrIt = new int[] { randomesque, (int)CatRcs.Utils.RowColumn.Sum(items) }.Min(); double infoVal = infos.ToList().OrderByDescending(n => n).ToArray()[nrIt - 1]; List <int> keep = new List <int>(); for (int k = 0; k < items.Length; k++) { if (infos[k] >= infoVal) { keep.Add(k + 1); } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), infos[select - 1], criterion, randomesque); } #endregion #region Criterion Type "MEPV" if (crit == ModelNames.CriterionTypes.MEPV) { int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] epvs = CatRcs.Utils.CommonHelper.Replicate(new double[] { 1000 }, itemBank.NumOfItems); for (int j = 0; j < items.Length; j++) { if (items[j] > 0) { epvs[j] = EPV.EPV_Calc(itemBank, j + 1, x, theta, itemBank.FindItem(Out), model, priorPar, parInt, D, priorDist); } } var tempVal = new int[] { randomesque, items.Sum() }.Min(); double epVal = epvs.ToList().OrderBy(n => n).ToArray()[tempVal - 1]; List <int> keep = new List <int>(); for (int k = 0; k < itemBank.NumOfItems; k++) { if (epvs[k] <= epVal) { keep.Add(k + 1); } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), epvs[select - 1], criterion, randomesque); } #endregion #region Criterion Type "random" if (crit == ModelNames.CriterionTypes.random) { int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a]] = 0; } } int gen = Convert.ToInt32(Convert.ToInt32(CatRcs.Utils.RandomNumberHandler.Runif(1, 0, 1)[0]) * items.Sum()) + 1; List <int> indexs = new List <int>(); for (int k = 0; k < itemBank.NumOfItems; k++) { if (items[k] > 0) { indexs.Add(k + 1); } } select = indexs.ElementAt(gen); result = new NextItemModel(select, itemBank.FindItem(select), double.NaN, criterion, randomesque); } #endregion #region Criterion Type "progressive" if (crit == ModelNames.CriterionTypes.progressive) { int item_administered = Out.Length; int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] info = Ii.Ii_Calc(theta, itemBank, model, D).Ii; List <double> tempItems = new List <double>(); for (int j = 0; j < items.Length; j++) { if (items[j] == 1) { tempItems.Add(info[j]); } } double wq = 0; double itemMaxInfo = tempItems.Max(); double[] randomValues = CatRcs.Utils.RandomNumberHandler.Runif(items.Length, 0, itemMaxInfo); if (rule == (int)ModelNames.RuleType.Precision) { double infostop = Math.Pow((1 / thr), 2); double cuminfo = Math.Pow(double.Parse((1 / SETH).ToString()), 2); if (item_administered > 0) { wq = Math.Pow(new double[] { cuminfo / infostop, item_administered / (maxItems - 1) }.Max(), AP); } } if (rule == (int)ModelNames.RuleType.Length) { if (item_administered > 0) { List <double> tempNum = new List <double>(); for (int i = 1; i <= item_administered; i++) { tempNum.Add(Math.Pow(i, AP)); } double numerador = tempNum.Sum(); List <double> tempDenom = new List <double>(); for (int j = 1; j <= thr - 1; j++) { tempDenom.Add(Math.Pow(j, AP)); } double denominador = tempDenom.Sum(); wq = numerador / denominador; } } double[] funcPR = info.Select((d, i) => d * wq + randomValues[i] * (1 - wq)).ToArray(); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { funcPR[OUT[a] - 1] = 0; } } List <int> keep = new List <int>(); for (int k = 0; k < funcPR.Length; k++) { if (funcPR[k] == funcPR.Max()) { keep.Add(k + 1); } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), info[select - 1], criterion, randomesque); } #endregion #region Criterion Type "proportional" if (crit == ModelNames.CriterionTypes.proportional) { int item_administered = Out.Length; int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double wq = 0; if (rule == (int)ModelNames.RuleType.Precision) { double infostop = Math.Pow((1 / thr), 2); double cuminfo = Math.Pow(double.Parse((1 / SETH).ToString()), 2); if (item_administered > 0) { wq = infostop * Math.Pow(new double[] { cuminfo / infostop, item_administered / (maxItems - 1) }.Max(), AP); } } if (rule == (int)ModelNames.RuleType.Length) { if (item_administered > 0) { List <double> tempNum = new List <double>(); for (int i = 1; i <= item_administered; i++) { tempNum.Add(Math.Pow(i, AP)); } double numerador = tempNum.Sum(); List <double> tempDenom = new List <double>(); for (int j = 1; j <= thr - 1; j++) { tempDenom.Add(Math.Pow(j, AP)); } double denominador = tempDenom.Sum(); wq = thr * numerador / denominador; } } double[] info = Ii.Ii_Calc(theta, itemBank, model, D).Ii; double[] infoPR = info.Select(s => Math.Pow(s, wq)).ToArray(); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { infoPR[OUT[a] - 1] = 0; } } List <double> tempInfoPR = new List <double>(); for (int k = 0; k < items.Length; k++) { if (items[k] == 1) { tempInfoPR.Add(infoPR[k]); } } double totalInfoPR = tempInfoPR.Sum(); double[] probSelect = infoPR.Select(m => m / totalInfoPR).ToArray(); int[] selectItems = items.Select((n, i) => i + 1).ToArray(); select = CatRcs.Utils.RandomNumberHandler.Sample(selectItems, 1, false)[0]; // prob parameter will be added after Sample functiom modification result = new NextItemModel(select, itemBank.FindItem(select), info[select], criterion, randomesque); } #endregion #region Criterion Type "thOpt" if (crit == ModelNames.CriterionTypes.thOpt) { if (string.IsNullOrEmpty(model)) // Only for Dichotomous Items { int[] items = CatRcs.Utils.CommonHelper.Replicate(new int[] { 1 }, itemBank.NumOfItems); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { items[OUT[a] - 1] = 0; } } double[] u = itemBank.GetItemParamter(CATItems.ColumnNames.c).Select((s, i) => - 0.75 + (s + itemBank.GetItemParamter(CATItems.ColumnNames.d)[i] + -2 * s * itemBank.GetItemParamter(CATItems.ColumnNames.d)[i]) / 2).ToArray(); double[] v = itemBank.GetItemParamter(CATItems.ColumnNames.c).Select((n, i) => (n + itemBank.GetItemParamter(CATItems.ColumnNames.d)[i] - 1) / 4).ToArray(); double[] xstar = u.Select((m, i) => 2 * Math.Sqrt(-m / 3) * Math.Cos(Math.Acos(-v[i] * Math.Sqrt(-27 / Math.Pow(m, 3)) / 2) / 3 + 4 * (Math.PI / 3)) + 0.5).ToArray(); double[] thstar = itemBank.GetItemParamter(CATItems.ColumnNames.b).Select((o, i) => o + Math.Log((xstar[i] - itemBank.GetItemParamter(CATItems.ColumnNames.c)[i]) / (itemBank.GetItemParamter(CATItems.ColumnNames.d)[i] - xstar[i])) / (D * itemBank.GetItemParamter(CATItems.ColumnNames.a)[i])).ToArray(); double[] distance = thstar.Select(p => Math.Abs(p - theta)).ToArray(); double[] ranks = CatRcs.Utils.CommonHelper.Rank(distance).Select(m => m).ToArray(); if (OUT != null) { for (int a = 0; a < OUT.Length; a++) { ranks[OUT[a] - 1] = -1; } } int nrIt = new int[] { randomesque, (int)CatRcs.Utils.RowColumn.Sum(items) }.Min(); List <double> tempRanks = new List <double>(); for (int j = 0; j < items.Length; j++) { if (items[j] == 1) { tempRanks.Add(ranks[j]); } } tempRanks = tempRanks.OrderBy(n => n).ToList(); double[] keepRank = tempRanks.GetRange(0, nrIt).ToArray(); keepRank = keepRank.Distinct().ToArray(); List <int> keep = new List <int>(); if (ranks.Length == items.Length) { for (int m = 0; m < keepRank.Length; m++) { for (int n = 0; n < ranks.Length; n++) { if ((items[n] == 1) && (ranks[n] == keepRank[m])) { keep.Add(n + 1); } } } } if (keep.Count == 1) { select = keep[0]; } else { select = CatRcs.Utils.RandomNumberHandler.Sample(keep.ToArray(), 1, false)[0]; } result = new NextItemModel(select, itemBank.FindItem(select), distance[select - 1], criterion, randomesque); } else { result = new NextItemModel(true, "thOpt's rule cannot be considered with polytomous items!"); return(result); } } #endregion #region Handling "cbControl" Parameter if (cbControl == null) { if (result != null) { result.prior_prop = null; result.post_prop = null; result.cb_prop = null; } } else { result.prior_prop = empProp; double[] postProp = new double[nrGroup]; string[] temp_grp = new string[Out.Length + 1]; for (int i = 0; i < temp_grp.Length; i++) { if (i == 0) { temp_grp[i] = cbGroup[result.item]; } temp_grp[i] = cbGroup[Out[i]]; } for (int j = 0; j < postProp.Length; j++) { string[] values = temp_grp.Where(m => m == cbControl.Names[j]).ToArray(); if (values != null && values.Length > 0) { postProp[j] = values.Length; } else { postProp[j] = 0; } } result.post_prop = postProp.Select(n => n / CatRcs.Utils.RowColumn.Sum(postProp)).ToArray(); result.cb_prop = thProp; } #endregion return(result); }
public static OIiList OIi_Calc(double th, CATItems it, int[] x, string model, double D) { OIiList objOIi = null; double[] OIi = null; try { if (String.IsNullOrEmpty(model)) { #region "Calculation for Dichotmous Items" PiList pr = Pi.Pi_Calc(th, it, model, D); if (pr == null) { objOIi = new OIiList(); objOIi.Exception = "No Pi values found!"; return(objOIi); } double[] P = pr.Pi; double[] dP = pr.dPi; double[] d2P = pr.d2Pi; OIi = new double[P.Length]; objOIi = new OIiList(P.Length); double[] Q = new double[P.Length]; for (int i = 0; i < P.Length; i++) { Q[i] = 1 - P[i]; } for (int j = 0; j < OIi.Length; j++) { OIi[j] = (P[j] * Q[j] * Math.Pow(dP[j], 2) - (x[0] - P[j]) * (P[j] * Q[j] * d2P[j] + Math.Pow(dP[j], 2) * (P[j] - Q[j]))) / (Math.Pow(P[j], 2) * Math.Pow(Q[j], 2)); } #endregion } else { #region "Calculation for Polytomous Items" PiListPoly pr = Pi.Pi_Poly_Calc(th, it, model, D); if (pr == null) { objOIi = new OIiList(); objOIi.Exception = "No Pi values found!"; return(objOIi); } double[,] P = pr.Pi; double[,] dP = pr.dPi; double[,] d2P = pr.d2Pi; OIi = new double[it.NumOfItems]; objOIi = new OIiList(it.NumOfItems); for (int i = 0; i < x.Length; i++) { double tempdP = dP[i, x[i]]; double tempP = P[i, x[i]]; double tempd2P = d2P[i, x[i]]; OIi[i] = (Math.Pow(dP[i, x[i]], 2) / Math.Pow(P[i, x[i]], 2)) - (d2P[i, x[i]] / P[i, x[i]]); } #endregion } objOIi.Add(OIi); } catch (Exception ex) { if (ex != null) { if (objOIi == null) { objOIi = new OIiList(); } objOIi.Exception = "No Pi value found!"; } return(objOIi); } return(objOIi); }
public void testEapEST_and_EapSEM_D() { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Test for item banks with different number of items for (int i1 = 0; i1 < numberOfItems.Length; i1++) { // Dichotomous Items DataFrame DichoItems = engineObj.Evaluate("DichoItems <- genDichoMatrix(items = " + numberOfItems[i1] + ")").AsDataFrame(); engineObj.SetSymbol("DichoItems", DichoItems); // Adapting with the existing "CAT-Items" type (Wrapper) CATItems itemBank = new CATItems(DichoItems[0].Select(y => (double)y).ToArray(), DichoItems[1].Select(y => (double)y).ToArray(), DichoItems[2].Select(y => (double)y).ToArray(), DichoItems[3].Select(y => (double)y).ToArray()); // test for different theta values double[] th = CatRcs.Utils.CommonHelper.Sequence(-6, 6, length: 11); var stopwatch = new Stopwatch(); stopwatch.Restart(); for (int i2 = 0; i2 < th.Length; i2++) { string temp = th[i2].ToString(nfi); //Creation of a response pattern for theta value NumericVector x_val = engineObj.Evaluate("x_val <- genPattern(" + th[i2].ToString(nfi) + ", DichoItems)").AsNumeric(); int[] x = x_val.Select(y => (int)y).ToArray(); // Call "EapEST" function from R NumericVector r_eapEst = engineObj.Evaluate("result_Eap <- eapEst(DichoItems, x_val)").AsNumeric(); // Call "EapSEM" function from R NumericVector r_eapSem = engineObj.Evaluate("result_EapSem <- eapSem(result_Eap, DichoItems, x_val)").AsNumeric(); stopwatch.Restart(); // Call "EapEST" function from CatRCS double cs_eapEst = CatRLib.EapEST(itemBank, x, ""); // Call "EapSEM" function from CatRCS double cs_eapSem = CatRLib.EapSEM(cs_eapEst, itemBank, x, ""); Console.WriteLine("Time: " + stopwatch.ElapsedMilliseconds); if (r_eapEst[0] - cs_eapEst > testEpsilon || r_eapSem[0] - cs_eapSem > testEpsilon) { resultFlag = false; } } } Assert.IsTrue(resultFlag, "Test Passed!"); }
public void testEPV_P(int NumOfItems, ModelNames.Models paramModel) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Polytomous Items CharacterVector modelName = engineObj.CreateCharacterVector(new string[] { paramModel.EnumToString() }); engineObj.SetSymbol("modelName", modelName); DataFrame PolyItems = engineObj.Evaluate("PolyItems <- genPolyMatrix(" + NumOfItems + ", 5, model = modelName, same.nrCat = TRUE)").AsDataFrame(); engineObj.SetSymbol("PolyItems", PolyItems); // Adapting with the existing "CAT-Items" type (Wrapper) Console.WriteLine("*******************************************"); Console.WriteLine("Polytomous Items, Model : " + paramModel.EnumToString()); Console.WriteLine("*******************************************"); CATItems itemBank = new CATItems(PolyItems[0].Length, paramModel.EnumToString(), 5); Tuple <CATItems.ColumnNames, int>[] cols = itemBank.GetKeys(); for (int i = 0; i < cols.Length; i++) { itemBank.SetItemParamter(cols[i], PolyItems[i].Select(y => (double)y).ToArray()); } #region "Test block for Ability Values (th)" double[] th = CatRcs.Utils.CommonHelper.Sequence(-6, 6, length: 11); for (int j = 0; j < th.Length; j++) { string temp = th[j].ToString(nfi); // Polytomous Items DataFrame it_given_R = engineObj.Evaluate("it_given_R <- PolyItems[c(4, 8),]").AsDataFrame(); engineObj.SetSymbol("it_given_R", it_given_R); //Creation of a response pattern for theta value engineObj.Evaluate("set.seed(1)"); NumericVector x_val = engineObj.Evaluate("x_val <- genPattern(" + th[j].ToString(nfi) + ", it_given_R, model = modelName)").AsNumeric(); engineObj.SetSymbol("x_val", x_val); int[] x = x_val.Select(y => (int)y).ToArray(); CATItems it_given = itemBank.FindItem(new int[] { 4, 8 }); // Call "EPV" function from R NumericVector r_epv = engineObj.Evaluate("r_epv <- EPV(PolyItems, 1, x_val, " + th[j].ToString(nfi) + ", it_given_R, model = modelName)").AsNumeric(); // Call "EPV" function from CatRCS double cs_epv = CatRLib.EPV(itemBank, 1, x, th[j], it_given, paramModel.EnumToString()); if (r_epv[0] - cs_epv > testEpsilon) { resultFlag = false; } } Assert.IsTrue(resultFlag); #endregion }
public void testPi_P_New(ModelNames.Models paramModel) { REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Polytomous Items CharacterVector modelName = engineObj.CreateCharacterVector(new string[] { paramModel.EnumToString() }); engineObj.SetSymbol("modelName", modelName); DataFrame PolyItems = engineObj.Evaluate("PolyItems <- genPolyMatrix(100, 5, model = modelName, same.nrCat = FALSE)").AsDataFrame(); engineObj.SetSymbol("PolyItems", PolyItems); // Adapting with the existing "CAT-Items" type (Wrapper) Console.WriteLine("*******************************************"); Console.WriteLine("Polytomous Items, Model : " + paramModel.EnumToString()); Console.WriteLine("*******************************************"); CATItems itemBank = new CATItems(NumOfItems: PolyItems[0].Length, model: paramModel.EnumToString(), nrCat: 5); for (int i = 0; i < itemBank.colSize; i++) { itemBank.all_items_poly[i] = PolyItems[i].Select(y => (double)y).ToArray(); } PiListPoly objPI = null; int decimalPoint = 4; double[] th_Values = CatRcs.Utils.CommonHelper.Sequence(-4, 4, by: 1); NumericVector th_val = engineObj.CreateNumericVector(new double[] { th_Values[0] }); engineObj.SetSymbol("th_val", th_val); // Calling the "Pi" from R GenericVector result_Pi = engineObj.Evaluate("result_Pi <- Pi(th = th_val, PolyItems, model = modelName, D = 1)").AsList(); // Getting the "Pi" function result NumericVector Pi = result_Pi[0].AsNumeric(); NumericVector dPi = result_Pi[1].AsNumeric(); NumericVector d2Pi = result_Pi[2].AsNumeric(); NumericVector d3Pi = result_Pi[3].AsNumeric(); Console.WriteLine("Value of Theta: " + th_Values[0]); // Calling "Pi" function objPI = CatRLib.Pi_P(th_Values[0], itemBank, paramModel.EnumToString(), 1); #region "Pi" int z = 0, pi_index = 0; resultFlag = true; Console.WriteLine("****** Pi ******"); int len = objPI.Pi.GetLength(0); int len2 = objPI.Pi.GetLength(1); for (int i = 0; i < objPI.Pi.GetLength(1); i++) // column { z = i + 1; // item number for (int j = 0; j < objPI.Pi.GetLength(0); j++) // row { double tempPiVal = !CatRcs.Utils.CheckNaValues.IsNaNvalue(Pi[pi_index]) ? Pi[pi_index] : 0; if (decimal.Round(Convert.ToDecimal(tempPiVal), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.Pi[j, i]), decimalPoint)) { Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } pi_index++; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of Pi are Matched!"); #endregion #region "dPi" z = 0; pi_index = 0; resultFlag = true; Console.WriteLine("****** dPi ******"); for (int i = 0; i < objPI.dPi.GetLength(1); i++) // column { z = i + 1; // item number for (int j = 0; j < objPI.dPi.GetLength(0); j++) // row { double tempPiVal = !CatRcs.Utils.CheckNaValues.IsNaNvalue(dPi[pi_index]) ? dPi[pi_index] : 0; if (decimal.Round(Convert.ToDecimal(tempPiVal), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.dPi[j, i]), decimalPoint)) { Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } pi_index++; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of dPi are Matched!"); #endregion #region "d2Pi" z = 0; pi_index = 0; resultFlag = true; Console.WriteLine("****** d2Pi ******"); for (int i = 0; i < objPI.d2Pi.GetLength(1); i++) // column { z = i + 1; // item number for (int j = 0; j < objPI.d2Pi.GetLength(0); j++) // row { double tempPiVal = !CatRcs.Utils.CheckNaValues.IsNaNvalue(d2Pi[pi_index]) ? d2Pi[pi_index] : 0; if (decimal.Round(Convert.ToDecimal(tempPiVal), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.d2Pi[j, i]), decimalPoint)) { Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } pi_index++; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of d2Pi are Matched!"); #endregion #region "d3Pi" z = 0; pi_index = 0; resultFlag = true; Console.WriteLine("****** d3Pi ******"); for (int i = 0; i < objPI.d3Pi.GetLength(1); i++) // column { z = i + 1; // item number for (int j = 0; j < objPI.d3Pi.GetLength(0); j++) // row { double tempPiVal = !CatRcs.Utils.CheckNaValues.IsNaNvalue(d3Pi[pi_index]) ? d3Pi[pi_index] : 0; if (decimal.Round(Convert.ToDecimal(tempPiVal), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.d3Pi[j, i]), decimalPoint)) { Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } pi_index++; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of d3Pi are Matched!"); #endregion }
// Optimization needed !!! public static double KL_Calc(CATItems itemBank, int item, int[] x, CATItems it_given, string model = null, double theta = 0, double[] priorPar = null, double[] X = null, double[] lik = null, int type = 1, double D = 1, string priorDist = "norm", double lower = -4, double upper = 4, int nqp = 33) { double res = 0; if ((type == (int)ModelNames.KLTypes.KL) || (type == (int)ModelNames.KLTypes.KLP)) // type is either "KL" or "KLP" { if (X != null && lik != null) { if (X.Length > 0 && lik.Length > 0) { if (X.Length != lik.Length) { return(res); // Error handling } } } if (theta == 0) { theta = CatRcs.ThetaEST.ThetaEst_Calc(it_given, x, D: D, model: model, method: CatRcs.Models.ModelNames.EstimaatorMethods.ML.EnumToString()); } double[] KLF = new double[nqp]; double[] crit_value = new double[nqp]; CATItems par = itemBank.FindItem(item); if (X == null) { X = CatRcs.Utils.CommonHelper.Sequence(lower, upper, nqp); } if (String.IsNullOrEmpty(model)) // Dichotomous Items { if (lik == null) { #region "Function 'L' " Func <double, int[], CATItems, double> L = (th, r, param) => { double result = 0; var temp_1 = Pi.Pi_Calc(th, param, model, D).Pi.Select((p, i) => Math.Pow(p, r[i])).ToArray(); var temp_2 = Pi.Pi_Calc(th, param, model, D).Pi.Select((p, i) => Math.Pow(1 - p, 1 - r[i])).ToArray(); if (temp_1.Length == temp_2.Length) { var temp_3 = temp_1.Select((p, i) => p * temp_2[i]).ToArray(); result = temp_3.Aggregate((acc, val) => acc * val); } return(result); }; #endregion lik = X.ToList().Select(a => L(a, x, it_given)).ToArray(); } for (int j = 0; j < KLF.Length; j++) { KLF[j] = Pi.Pi_Calc(theta, par, model, D).Pi[0] * Math.Log(Pi.Pi_Calc(theta, par, model, D).Pi[0] / Pi.Pi_Calc(X[j], par, model, D).Pi[0], Math.Exp(1)) + (1 - Pi.Pi_Calc(theta, par, model, D).Pi[0]) * Math.Log((1 - Pi.Pi_Calc(theta, par, model, D).Pi[0]) / (1 - Pi.Pi_Calc(X[j], par, model, D).Pi[0]), Math.Exp(1)); } crit_value = KLF.ToList().Select((c, i) => c * lik[i]).ToArray(); if ((type == (int)ModelNames.KLTypes.KLP)) { double[] pd = null; switch (priorDist) { case "norm": pd = CatRcs.Utils.CommonHelper.Dnorm(X, priorPar[0], priorPar[1]); break; case "unif": pd = CatRcs.Utils.CommonHelper.Dunif(X, priorPar[0], priorPar[1]); break; } crit_value = crit_value.ToList().Select((c, i) => c * pd[i]).ToArray(); } } else // Polytomous Items { if (lik == null) { #region "Function 'LL' " Func <double, CATItems, int[], double> LL = (th, param, r) => { double result = 1; double[,] prob = Pi.Pi_Poly_Calc(th, param, model, D).Pi; for (int i = 0; i < r.Length; i++) { result = result * prob[i, r[i]]; } return(result); }; #endregion lik = X.ToList().Select(a => LL(a, it_given, x)).ToArray(); } double[,] pi = Pi.Pi_Poly_Calc(theta, par, model, D).Pi; for (int i = 0; i < X.Length; i++) { double[,] pri = Pi.Pi_Poly_Calc(X[i], par, model, D).Pi; double[] tempPi = new double[pi.Length]; for (int j = 0; j < pi.Length; j++) { tempPi[j] = pi[0, j] * Math.Log(pi[0, j] / pri[0, j]); } KLF[i] = CatRcs.Utils.RowColumn.Sum(tempPi); } crit_value = KLF.ToList().Select((c, i) => c * lik[i]).ToArray(); if ((type == (int)ModelNames.KLTypes.KLP)) { double[] pd = null; switch (priorDist) { case "norm": pd = CatRcs.Utils.CommonHelper.Dnorm(X, priorPar[0], priorPar[1]); break; case "unif": pd = CatRcs.Utils.CommonHelper.Dunif(X, priorPar[0], priorPar[1]); break; } crit_value = crit_value.ToList().Select((c, i) => c * pd[i]).ToArray(); } } res = CatRcs.Integrate_catR.Integrate_CatR_Calc(X, crit_value); } else { return(res); } return(res); }
public void test_StartItems_D(int numofItems) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Dichotomous Items DataFrame DichoItems = engineObj.Evaluate("DichoItems <- genDichoMatrix(items = " + numofItems + ")").AsDataFrame(); engineObj.SetSymbol("DichoItems", DichoItems); // Adapting with the existing "CAT-Items" type (Wrapper) CATItems itemBank = new CATItems(DichoItems[0].Length, false); // New Dictionary itemBank.SetItemParamter(CATItems.ColumnNames.a, DichoItems[0].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.b, DichoItems[1].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.c, DichoItems[2].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.d, DichoItems[3].Select(y => (double)y).ToArray()); // Call "StartItems" function from R, "MFI" criterion GenericVector r_StartItems = engineObj.Evaluate("r_StartItems <- startItems(DichoItems, nrItems = 3, theta = 1, halfRange = 2)").AsList(); // Resulting item numbers IntegerVector items = r_StartItems[0].AsInteger(); DataFrame tempitems = r_StartItems[1].AsDataFrame(); // Resulting Items CATItems r_CatItems = new CATItems(tempitems[0].Length, false); r_CatItems.SetItemParamter(CATItems.ColumnNames.a, tempitems[0].Select(y => (double)y).ToArray()); r_CatItems.SetItemParamter(CATItems.ColumnNames.b, tempitems[1].Select(y => (double)y).ToArray()); r_CatItems.SetItemParamter(CATItems.ColumnNames.c, tempitems[2].Select(y => (double)y).ToArray()); r_CatItems.SetItemParamter(CATItems.ColumnNames.d, tempitems[3].Select(y => (double)y).ToArray()); // Ability value NumericVector thStart = r_StartItems[2].AsNumeric(); // Criterion CharacterVector startSelect = r_StartItems[3].AsCharacter(); // Call "StartItems" function from CS StartItemsModel cs_StartItems = CatRLib.StartItems(itemBank, nrItems: 3, theta: 1, halfRange: 2); // Check selected items if (items.Length == cs_StartItems.items.Length) { for (int ind = 0; ind < cs_StartItems.items.Length; ind++) { if (items[ind] != cs_StartItems.items[ind]) { resultFlag = false; } } } // Check starting ability values if (thStart.Length == cs_StartItems.thStart.Length) { for (int ind2 = 0; ind2 < cs_StartItems.thStart.Length; ind2++) { if (thStart[ind2] != cs_StartItems.thStart[ind2]) { resultFlag = false; } } } Assert.IsTrue(resultFlag); }
public void test_NextItem_D(int numofItems, ModelNames.CriterionTypes paramCriterion) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Dichotomous Items DataFrame DichoItems = engineObj.Evaluate("DichoItems <- genDichoMatrix(items = " + numofItems + ")").AsDataFrame(); engineObj.SetSymbol("DichoItems", DichoItems); // Adapting with the existing "CAT-Items" type (Wrapper) CATItems itemBank = new CATItems(DichoItems[0].Length, false); // New Dictionary itemBank.SetItemParamter(CATItems.ColumnNames.a, DichoItems[0].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.b, DichoItems[1].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.c, DichoItems[2].Select(y => (double)y).ToArray()); itemBank.SetItemParamter(CATItems.ColumnNames.d, DichoItems[3].Select(y => (double)y).ToArray()); // Call "thetaEst" function //NumericVector r_th = engineObj.Evaluate("r_th <- thetaEst(rbind(DichoItems[3,], DichoItems[13,]), c(0, 1), method = \"WL\")").AsNumeric(); //engineObj.SetSymbol("r_th", r_th); //double cs_th = CatRLib.ThetaEst(itemBank.FindItem(new int[] { 3, 13 }), x: new int[] { 0, 1 }, model: "", method: ModelNames.EstimaatorMethods.WL.EnumToString()); // Call "NextItem" function from R with parameter "out" GenericVector r_NextItem = engineObj.Evaluate("r_NextItem <- nextItem(DichoItems, theta = 0, out = c(3, 13), criterion = \"" + paramCriterion.ToString() + "\")").AsList(); // Call "NextItem" function from R with response pattern "x" //GenericVector r_NextItem = engineObj.Evaluate("r_NextItem <- nextItem(DichoItems, x = c(0, 1), out = c(3, 13), theta = r_th, criterion = \"" + paramCriterion.ToString() + "\")").AsList(); // Selected item NumericVector item = r_NextItem[0].AsNumeric(); DataFrame par = r_NextItem[1].AsDataFrame(); // Item parameter CATItems parItems = new CATItems(par[0].Length, false); parItems.SetItemParamter(CATItems.ColumnNames.a, par[0].Select(y => (double)y).ToArray()); parItems.SetItemParamter(CATItems.ColumnNames.b, par[1].Select(y => (double)y).ToArray()); parItems.SetItemParamter(CATItems.ColumnNames.c, par[2].Select(y => (double)y).ToArray()); parItems.SetItemParamter(CATItems.ColumnNames.d, par[3].Select(y => (double)y).ToArray()); // Value of "info" NumericVector info = r_NextItem[2].AsNumeric(); // Criterion CharacterVector startSelect = r_NextItem[3].AsCharacter(); // Call "NextItem" function from CS with parameter "out" NextItemModel cs_NextItem = CatRLib.NextItem(itemBank, theta: 0, Out: new int[] { 3, 13 }, criterion: (int)paramCriterion); // Call "NextItem" function from CS with response pattern "x" //NextItemModel cs_NextItem = CatRLib.NextItem(itemBank, theta: cs_th, Out: new int[] { 3, 13 }, x: new int[] { 0, 1 }, criterion: (int)paramCriterion); // Checking item & other values if (item[0] != cs_NextItem.item) { resultFlag = false; } if (decimal.Round((decimal)info[0], 3) != decimal.Round((decimal)cs_NextItem.info, 3)) { resultFlag = false; } Assert.IsTrue(resultFlag); }
public void test_StartItems_P(int numofItems, ModelNames.Models paramModel) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Polytomous Items CharacterVector modelName = engineObj.CreateCharacterVector(new string[] { paramModel.EnumToString() }); engineObj.SetSymbol("modelName", modelName); DataFrame PolyItems = engineObj.Evaluate("PolyItems <- genPolyMatrix(" + numofItems + ", 5, model = modelName, same.nrCat = TRUE)").AsDataFrame(); engineObj.SetSymbol("PolyItems", PolyItems); // Adapting with the existing "CAT-Items" type (Wrapper) Console.WriteLine("*******************************************"); Console.WriteLine("Polytomous Items, Model : " + paramModel.EnumToString()); Console.WriteLine("*******************************************"); CATItems itemBank = new CATItems(PolyItems[0].Length, paramModel.EnumToString(), 5); Tuple <CATItems.ColumnNames, int>[] cols = itemBank.GetKeys(); for (int i = 0; i < cols.Length; i++) { itemBank.SetItemParamter(cols[i], PolyItems[i].Select(y => (double)y).ToArray()); } // Call "StartItems" function from R, "MFI" criterion GenericVector r_StartItems = engineObj.Evaluate("r_StartItems <- startItems(PolyItems, model = modelName, nrItems = 3, theta = 1, halfRange = 2)").AsList(); // Resulting item numbers IntegerVector items = r_StartItems[0].AsInteger(); DataFrame tempitems = r_StartItems[1].AsDataFrame(); // Resulting Items CATItems r_CatItems = new CATItems(tempitems[0].Length, paramModel.EnumToString(), 5); for (int i = 0; i < cols.Length; i++) { r_CatItems.SetItemParamter(cols[i], tempitems[i].Select(y => (double)y).ToArray()); } // Resulting NumericVector thStart = r_StartItems[2].AsNumeric(); CharacterVector startSelect = r_StartItems[3].AsCharacter(); // Call "StartItems" function from CS StartItemsModel cs_StartItems = CatRLib.StartItems(itemBank, paramModel.EnumToString(), nrItems: 3, theta: 1, halfRange: 2); // Check items if (items.Length == cs_StartItems.items.Length) { for (int ind = 0; ind < cs_StartItems.items.Length; ind++) { if (items[ind] != cs_StartItems.items[ind]) { resultFlag = false; } } } // Check starting ability values if (thStart.Length == cs_StartItems.thStart.Length) { for (int ind2 = 0; ind2 < cs_StartItems.thStart.Length; ind2++) { if (thStart[ind2] != cs_StartItems.thStart[ind2]) { resultFlag = false; } } } Assert.IsTrue(resultFlag); }
public static IiList Ii_Calc(double th, CATItems it, string model, double D) { IiList objIi = null; double[] Ii = null; double[] dIi = null; double[] d2Ii = null; try { if (String.IsNullOrEmpty(model)) { #region "Calculation for Dichotmous Items" double[] P = null; double[] dP = null; double[] d2P = null; double[] d3P = null; PiList pr = Pi.Pi_Calc(th, it, model, D); // Check return value of Pi if (pr == null) { objIi = new IiList(); objIi.Exception = "No Pi values found!"; return(objIi); } P = pr.Pi; dP = pr.dPi; d2P = pr.d2Pi; d3P = pr.d3Pi; Ii = new double[dP.Length]; dIi = new double[d2P.Length]; d2Ii = new double[d3P.Length]; objIi = new IiList(P.Length); double[] Q = new double[P.Length]; for (int i = 0; i < P.Length; i++) { Q[i] = 1 - P[i]; } for (int j = 0; j < Ii.Length; j++) { Ii[j] = Math.Pow(dP[j], 2) / (P[j] * Q[j]); } for (int k = 0; k < dIi.Length; k++) { dIi[k] = dP[k] * (2 * P[k] * Q[k] * d2P[k] - Math.Pow(dP[k], 2) * (Q[k] - P[k])) / (Math.Pow(P[k], 2) * Math.Pow(Q[k], 2)); } for (int l = 0; l < d2Ii.Length; l++) { d2Ii[l] = (2 * P[l] * Q[l] * (Math.Pow(d2P[l], 2) + dP[l] * d3P[l]) - 2 * Math.Pow(dP[l], 2) * d2P[l] * (Q[l] - P[l])) / (Math.Pow(P[l], 2) * Math.Pow(Q[l], 2)) - (3 * Math.Pow(P[l], 2) * Q[l] * Math.Pow(dP[l], 2) * d2P[l] - P[l] * Math.Pow(dP[l], 4) * (2 * Q[l] - P[l])) / (Math.Pow(P[l], 4) * Math.Pow(Q[l], 2)) + (3 * P[l] * Math.Pow(Q[l], 2) * Math.Pow(dP[l], 2) * d2P[l] - Q[l] * Math.Pow(dP[l], 4) * (Q[l] - 2 * P[l])) / (Math.Pow(P[l], 2) * Math.Pow(Q[l], 4)); } #endregion } else { #region "Calculation for Polytomous Items" double[,] P = null; double[,] dP = null; double[,] d2P = null; double[,] d3P = null; PiListPoly pr = Pi.Pi_Poly_Calc(th, it, model, D); if (pr == null) { objIi = new IiList(); objIi.Exception = "No Pi values found!"; return(objIi); } P = pr.Pi; dP = pr.dPi; d2P = pr.d2Pi; d3P = pr.d3Pi; int rowLength = pr.Pi.GetLength(0); int columnLength = pr.Pi.GetLength(1); objIi = new IiList(rowLength); double[,] pr0 = new double[rowLength, columnLength]; double[,] pr1 = new double[rowLength, columnLength]; double[,] pr2 = new double[rowLength, columnLength]; Ii = new double[rowLength]; dIi = new double[rowLength]; d2Ii = new double[rowLength]; for (int i = 0; i < rowLength; i++) { for (int j = 0; j < columnLength; j++) { pr0[i, j] = Math.Pow(dP[i, j], 2) / P[i, j]; pr1[i, j] = 2 * dP[i, j] * (d2P[i, j] / P[i, j]) - (Math.Pow(dP[i, j], 3) / Math.Pow(P[i, j], 2)); pr2[i, j] = (2 * Math.Pow(d2P[i, j], 2) + 2 * dP[i, j] * d3P[i, j]) / P[i, j] - 2 * Math.Pow(dP[i, j], 2) * (d2P[i, j] / -3) * dP[i, j] * (d2P[i, j] / Math.Pow(P[i, j], 2)) + 2 * (Math.Pow(dP[i, j], 4) / Math.Pow(P[i, j], 3)); } } Ii = RowColumn.rowSums(pr0); dIi = RowColumn.rowSums(pr1); d2Ii = RowColumn.rowSums(pr2); #endregion } objIi.Add(Ii, dIi, d2Ii); } catch (Exception ex) { if (ex != null) { if (objIi == null) { objIi = new IiList(); } objIi.Exception = ex.Message; } return(objIi); } return(objIi); }
// Optimized CAT Items public static double EPV_Calc(CATItems itemBank, int item, int[] x, double theta, CATItems it_given, string model, double[] priorPar = null, int[] parInt = null, double D = 1, string priorDist = "norm") { double res = 0; double th = theta; if (priorPar == null || priorPar.Length < 2) { priorPar = new double[2]; priorPar[0] = 0; priorPar[1] = 1; } if (parInt == null || parInt.Length < 3) { parInt = new int[3]; parInt[0] = -4; parInt[1] = 4; parInt[2] = 33; } if (String.IsNullOrEmpty(model)) // Dichotomous Items { CATItems itj = itemBank.AddItem_D(it_given, new int[] { item }); double p1 = Pi.Pi_Calc(th, itemBank, model, D).Pi[item - 1]; // item is matched with the array index double p0 = 1 - p1; int[] temp_x = new int[x.Length + 1]; for (int i = 0; i < x.Length; i++) { temp_x[i] = x[i]; } temp_x[x.Length - 1] = 0; double th0 = EapEST.EapEST_Calc(itj, temp_x, "", priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]); double var0 = Math.Pow(EapSEM.EapSEM_Calc(th0, itj, temp_x, "", priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]), 2); temp_x = new int[x.Length + 1]; for (int i = 0; i < x.Length; i++) { temp_x[i] = x[i]; } temp_x[x.Length - 1] = 1; double th1 = EapEST.EapEST_Calc(itj, temp_x, "", priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]); double var1 = Math.Pow(EapSEM.EapSEM_Calc(th1, itj, temp_x, "", priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]), 2); res = (p0 * var0) + (p1 * var1); } else // Polytomous Items !!!! Optimization needed !!!! { double[,] temp_Pi = Pi.Pi_Poly_Calc(th, itemBank, model, D).Pi; // Already returns a NA free list of values. // !! Optimize !! List <double> probs = new List <double>(); for (int i = 0; i < temp_Pi.GetLength(1); i++) { probs.Add(temp_Pi[0, i]); } // !!!! Add new method for polytomous items !!!! CATItems it_new = it_given; double[] th_new = new double[probs.Count]; double[] se_new = new double[probs.Count]; List <int> temp_x = new List <int>(); for (int j = 0; j < probs.Count; j++) { temp_x = x.ToList(); temp_x.Add(j); th_new[j] = EapEST.EapEST_Calc(it_new, temp_x.ToArray(), "", priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]); se_new[j] = Math.Pow(EapSEM.EapSEM_Calc(th_new[j], it_new, temp_x.ToArray(), "", priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]), 2); } res = CatRcs.Utils.RowColumn.Sum(probs.Select((p, s) => p * se_new[s]).ToArray()); } return(res); }
internal static double EapSEM_Calc(double thEst, CATItems it, int[] x, string model, double[] priorPar = null, double D = 1, string priorDist = "norm", double lower = -4, double upper = 4, double nqp = 33) { double res = 0; double[] X = CatRcs.Utils.CommonHelper.Sequence(lower, upper, nqp); double[] Y1 = null; double[] Y2 = null; if (priorPar == null || priorPar.Length < 2) { priorPar = new double[2]; priorPar[0] = 0; priorPar[1] = 1; } if (String.IsNullOrEmpty(model)) // Dichotomous Items { #region "Function 'L' " Func <double, CATItems, int[], double> L = (th, items, x_in) => { double result = 0; double[] pi = Pi.Pi_Calc(th, it, model, D).Pi; double[] x_p = new double[pi.Length]; double[] x_q = new double[pi.Length]; double[] p_q = new double[pi.Length]; for (int ind_p = 0; ind_p < pi.Length; ind_p++) { x_p[ind_p] = Math.Pow(pi[ind_p], x_in[ind_p]);; x_q[ind_p] = Math.Pow(1 - pi[ind_p], 1 - x_in[ind_p]); p_q[ind_p] = x_p[ind_p] * x_q[ind_p]; } result = p_q.Aggregate((acc, val) => acc * val); return(result); }; #endregion #region "Function 'g' " Func <double[], double[]> g = (s) => { double[] resList = new double[s.Length]; for (int i = 0; i < s.Length; i++) { switch (priorDist) { case "norm": resList[i] = Math.Pow(s[i] - thEst, 2) * CatRcs.Utils.CommonHelper.Dnorm(s[i], priorPar[0], priorPar[1]) * L(s[i], it, x); break; case "unif": resList[i] = Math.Pow(s[i] - thEst, 2) * CatRcs.Utils.CommonHelper.Dunif(s[i], priorPar[0], priorPar[1]) * L(s[i], it, x); break; case "Jeffreys": resList[i] = Math.Pow(s[i] - thEst, 2) * Math.Sqrt(CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(s[i], it, model, D).Ii)) * L(s[i], it, x); break; } } return(resList); }; #endregion #region "Function 'h' " Func <double[], double[]> h = (s) => { double[] resList = new double[s.Length]; for (int i = 0; i < s.Length; i++) { switch (priorDist) { case "norm": resList[i] = CatRcs.Utils.CommonHelper.Dnorm(s[i], priorPar[0], priorPar[1]) * L(s[i], it, x); break; case "unif": resList[i] = CatRcs.Utils.CommonHelper.Dunif(s[i], priorPar[0], priorPar[1]) * L(s[i], it, x); break; case "Jeffreys": resList[i] = Math.Sqrt(CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(s[i], it, model, D).Ii)) * L(s[i], it, x); break; } } return(resList); }; #endregion Y1 = g(X); Y2 = h(X); } else // Polytomous Items { #region "Function 'LL' " Func <double, CATItems, int[], double> LL = (th, items, x_in) => { double result = 1; double[,] prob = Pi.Pi_Poly_Calc(th, it, model, D).Pi; for (int i = 0; i < x_in.Length; i++) { result = result * prob[i, x_in[i]]; } return(result); }; #endregion #region "Function 'gg' " Func <double[], double[]> gg = (s) => { double[] resList = new double[s.Length]; for (int i = 0; i < s.Length; i++) { switch (priorDist) { case "norm": resList[i] = Math.Pow(s[i] - thEst, 2) * CatRcs.Utils.CommonHelper.Dnorm(s[i], priorPar[0], priorPar[1]) * LL(s[i], it, x); break; case "unif": resList[i] = Math.Pow(s[i] - thEst, 2) * CatRcs.Utils.CommonHelper.Dunif(s[i], priorPar[0], priorPar[1]) * LL(s[i], it, x); break; case "Jeffreys": resList[i] = Math.Pow(s[i] - thEst, 2) * Math.Sqrt(CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(s[i], it, model, D).Ii)) * LL(s[i], it, x); break; } } return(resList); }; #endregion #region "Function 'hh' " Func <double[], double[]> hh = (s) => { double[] resList = new double[s.Length]; for (int i = 0; i < s.Length; i++) { switch (priorDist) { case "norm": resList[i] = CatRcs.Utils.CommonHelper.Dnorm(s[i], priorPar[0], priorPar[1]) * LL(s[i], it, x); break; case "unif": resList[i] = CatRcs.Utils.CommonHelper.Dunif(s[i], priorPar[0], priorPar[1]) * LL(s[i], it, x); break; case "Jeffreys": resList[i] = Math.Sqrt(CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(s[i], it, model, D).Ii)) * LL(s[i], it, x); break; } } return(resList); }; #endregion Y1 = gg(X); Y2 = hh(X); } if ((Y1 != null) && (Y2 != null)) { res = Math.Sqrt(CatRcs.Integrate_catR.Integrate_CatR_Calc(X, Y1) / CatRcs.Integrate_catR.Integrate_CatR_Calc(X, Y2)); } return(res); }
public static double ThetaEst_Calc(CATItems it, int[] x, string model = null, double[] priorPar = null, double[] range = null, int[] parInt = null, double D = 1, string method = "BM", string priorDist = "norm") { double result = 0; double[] RANGE = null; #region "Parameter Validation" if (priorPar == null || priorPar.Length < 2) { priorPar = new double[2]; priorPar[0] = 0; priorPar[1] = 1; } if (range == null || range.Length < 2) { range = new double[2]; range[0] = -4; range[1] = 4; } if (parInt == null || parInt.Length < 3) { parInt = new int[3]; parInt[0] = -4; parInt[1] = 4; parInt[2] = 33; } #endregion if (method == ModelNames.EstimaatorMethods.EAP.EnumToString()) { result = EapEST.EapEST_Calc(it, x, model, priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]); } else { if (String.IsNullOrEmpty(model)) // Dichotomous Items { #region "Function 'r0' " Func <double, string, double> r0 = (th, met) => { double res = 0; if (met == ModelNames.EstimaatorMethods.BM.EnumToString()) { switch (priorDist) { case "norm": res = (priorPar[0] - th) / Math.Pow(priorPar[1], 2); break; case "unif": res = 0; break; case "Jeffreys": IiList objIi = Ii.Ii_Calc(th, it, model, D); res = CatRcs.Utils.RowColumn.Sum(objIi.dIi) / (2 * CatRcs.Utils.RowColumn.Sum(objIi.Ii)); break; } } else { ModelNames.EstimaatorMethods md = ModelNames.StringToEnumMethods(met); switch (md) { case ModelNames.EstimaatorMethods.ML: res = 0; break; case ModelNames.EstimaatorMethods.WL: res = CatRcs.Utils.RowColumn.Sum(Ji.Ji_Calc(th, it, model, D).Ji) / (2 * CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(th, it, model, D).Ii)); break; } } return(res); }; #endregion #region "Function 'r' " Func <double, double> r = (th) => { double res = 0; double[] Q = new double[it.NumOfItems], x_p = new double[it.NumOfItems], p_q = new double[it.NumOfItems], temp = new double[it.NumOfItems]; double[] pi = Pi.Pi_Calc(th, it, model, D).Pi; double[] dpi = Pi.Pi_Calc(th, it, model, D).dPi; for (int ind_p = 0; ind_p < pi.Length; ind_p++) { Q[ind_p] = 1 - pi[ind_p]; x_p[ind_p] = x[ind_p] - pi[ind_p]; p_q[ind_p] = pi[ind_p] * Q[ind_p]; temp[ind_p] = dpi[ind_p] * (x_p[ind_p] / p_q[ind_p]); } res = temp.Sum(); return(res); }; #endregion #region "Function 'f' " Func <double, double> f = (th) => { double res = 0; return(res); }; if (method == ModelNames.EstimaatorMethods.BM.EnumToString() && priorDist == "unif") { f = (th) => { double res = 0; string methodName = ModelNames.EstimaatorMethods.ML.EnumToString(); res = r0(th, methodName) + r(th); return(res); }; } else { f = (th) => { double res = 0; res = r0(th, method) + r(th); return(res); }; } #endregion if (method == ModelNames.EstimaatorMethods.BM.EnumToString() && priorDist == "unif") { RANGE = priorPar; } else { RANGE = range; } if (f(RANGE[0]) < 0 && f(RANGE[1]) < 0) { result = RANGE[0]; } else { if (f(RANGE[0]) > 0 && f(RANGE[1]) > 0) { result = RANGE[1]; } else { result = CatRcs.Utils.Maths.UniRoot(f, RANGE).root; } } } else // Polytomous Items { int met = 0, pd = 0; ModelNames.EstimaatorMethods md = ModelNames.StringToEnumMethods(method); #region "Conditional Block" switch (md) { case ModelNames.EstimaatorMethods.ML: met = 1; break; case ModelNames.EstimaatorMethods.BM: met = 2; break; case ModelNames.EstimaatorMethods.WL: met = 3; break; case ModelNames.EstimaatorMethods.EAP: met = 4; break; } switch (priorDist) { case "norm": pd = 1; break; case "unif": pd = 2; break; case "Jeffreys": pd = 3; break; } if (met == 2 && pd == 2) { RANGE = new double[priorPar.Length]; RANGE[0] = Math.Max(priorPar[0], range[0]); RANGE[1] = Math.Min(priorPar[1], range[1]); } else { RANGE = range; } #endregion #region "Function 'dl' " Func <double, double> dl = (th) => { double res = 0; PiListPoly p = Pi.Pi_Poly_Calc(th, it, model, D); double[,] pr = p.Pi; double[,] dpr = p.dPi; for (int i = 0; i < x.Length; i++) { res = res + dpr[i, x[i]] / pr[i, x[i]]; } return(res); }; #endregion #region "Function 'f0' " Func <double, double> f0 = (th) => { double res = 0; if (met == 2) { switch (pd.ToString()) { case "1": res = (priorPar[0] - th) / Math.Pow(priorPar[1], 2); break; case "2": res = 0; break; case "3": IiList objIi = CatRcs.Ii.Ii_Calc(th, it, model, D); res = CatRcs.Utils.RowColumn.Sum(objIi.dIi) / (2 * CatRcs.Utils.RowColumn.Sum(objIi.Ii)); break; } } else { switch (met.ToString()) { case "1": res = 0; break; case "2": res = 0; break; case "3": res = CatRcs.Utils.RowColumn.Sum(CatRcs.Ji.Ji_Calc(th, it, model, D).Ji) / (2 * CatRcs.Utils.RowColumn.Sum(CatRcs.Ii.Ii_Calc(th, it, model, D).Ii)); break; } } return(res); }; #endregion #region "Function 'optF' " Func <double, double> optF = (th) => { double res = 0; res = dl(th) + f0(th); return(res); }; #endregion if (optF(RANGE[0]) < 0 && optF(RANGE[1]) < 0) { result = RANGE[0]; } else { if (optF(RANGE[0]) > 0 && optF(RANGE[1]) > 0) { result = RANGE[1]; } else { result = CatRcs.Utils.Maths.UniRoot(optF, RANGE).root; } } } } return(result); }
public static double SemTheta_Calc(double thEst, CATItems it, int[] x = null, string model = null, double[] priorPar = null, int[] parInt = null, double D = 1, string method = "BM", string priorDist = "norm") { double result = 0; if (priorPar == null || priorPar.Length < 2) { priorPar = new double[2]; priorPar[0] = 0; priorPar[1] = 1; } if (parInt == null || parInt.Length < 3) { parInt = new int[3]; parInt[0] = -4; parInt[1] = 4; parInt[2] = 33; } if (method == ModelNames.EstimaatorMethods.EAP.EnumToString()) { result = EapSEM.EapSEM_Calc(thEst, it, x, model, priorPar, D, priorDist, parInt[0], parInt[1], parInt[2]); } else { if (String.IsNullOrEmpty(model)) // Dichotomous Items { #region "Function 'dr0' " Func <double> dr0 = () => { double res = 0; if (method == ModelNames.EstimaatorMethods.BM.EnumToString()) { switch (priorDist) { case "norm": res = -1 / (Math.Pow(priorPar[1], 2)); break; case "unif": res = 0; break; case "Jeffreys": IiList objIi = Ii.Ii_Calc(thEst, it, model, D); res = (CatRcs.Utils.RowColumn.Sum(objIi.d2Ii) * CatRcs.Utils.RowColumn.Sum(objIi.Ii) - Math.Pow(CatRcs.Utils.RowColumn.Sum(objIi.dIi), 2)) / (2 * Math.Pow(CatRcs.Utils.RowColumn.Sum(objIi.Ii), 2)); break; } } else { if (method == ModelNames.EstimaatorMethods.ML.EnumToString() || method == ModelNames.EstimaatorMethods.WL.EnumToString()) { res = 0; } } return(res); }; #endregion result = 1 / Math.Sqrt(-dr0() + CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(thEst, it, model, D).Ii)); } else // Polytomous Items { double met = 0, pd = 0, optI = 0; ModelNames.EstimaatorMethods md = ModelNames.StringToEnumMethods(method); switch (md) { case ModelNames.EstimaatorMethods.ML: met = 1; break; case ModelNames.EstimaatorMethods.BM: met = 2; break; case ModelNames.EstimaatorMethods.WL: met = 3; break; case ModelNames.EstimaatorMethods.EAP: met = 4; break; } switch (priorDist) { case "norm": pd = 1; break; case "unif": pd = 2; break; case "Jeffreys": pd = 3; break; } if (met == 1 || (met == 2 && pd == 2)) { optI = CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(thEst, it, model, D).Ii); } if (met == 2 && pd == 1) { optI = CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(thEst, it, model, D).Ii) + (1 / Math.Pow(priorPar[1], 2)); } if (met == 3 || (met == 2 && pd == 3)) { IiList objIi = Ii.Ii_Calc(thEst, it, model, D); if (met == 2) { optI = CatRcs.Utils.RowColumn.Sum(objIi.Ii) + (Math.Pow(CatRcs.Utils.RowColumn.Sum(objIi.dIi), 2) - CatRcs.Utils.RowColumn.Sum(objIi.d2Ii) * CatRcs.Utils.RowColumn.Sum(objIi.Ii)) / (2 * Math.Pow(CatRcs.Utils.RowColumn.Sum(objIi.Ii), 2)); } else { optI = CatRcs.Utils.RowColumn.Sum(objIi.Ii); } } result = 1 / Math.Sqrt(optI); } } return(result); }
public void testKL_P(int NumOfItems, ModelNames.Models paramModel) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Polytomous Items CharacterVector modelName = engineObj.CreateCharacterVector(new string[] { paramModel.EnumToString() }); engineObj.SetSymbol("modelName", modelName); DataFrame PolyItems = engineObj.Evaluate("PolyItems <- genPolyMatrix(" + NumOfItems + ", 5, model = modelName, same.nrCat = TRUE)").AsDataFrame(); engineObj.SetSymbol("PolyItems", PolyItems); // Adapting with the existing "CAT-Items" type (Wrapper) Console.WriteLine("*******************************************"); Console.WriteLine("Polytomous Items, Model : " + paramModel.EnumToString()); Console.WriteLine("*******************************************"); CATItems itemBank = new CATItems(PolyItems[0].Length, paramModel.EnumToString(), 5); Tuple <CATItems.ColumnNames, int>[] cols = itemBank.GetKeys(); for (int i = 0; i < cols.Length; i++) { itemBank.SetItemParamter(cols[i], PolyItems[i].Select(y => (double)y).ToArray()); } DataFrame it_given_R = engineObj.Evaluate("it_given_R <- PolyItems[c(4, 8),]").AsDataFrame(); engineObj.SetSymbol("it_given_R", it_given_R); CATItems it_given = itemBank.FindItem(new int[] { 4, 8 }); //Creation of a response pattern for theta value engineObj.Evaluate("set.seed(1)"); NumericVector x_val = engineObj.Evaluate("x_val <- genPattern(0, it_given_R, model = modelName)").AsNumeric(); engineObj.SetSymbol("x_val", x_val); int[] x = x_val.Select(y => (int)y).ToArray(); // Call "thetaEST" function from R, method = \"ML\" NumericVector Theta = engineObj.Evaluate("Theta <- thetaEst(it_given_R, x_val, method = \"ML\", model = modelName)").AsNumeric(); // Call "KL" function from R NumericVector r_KL = engineObj.Evaluate("r_KL <- KL(PolyItems, 1, x_val, it_given_R, theta = Theta, model = modelName)").AsNumeric(); // Call "thetaEST" function from CS double th_est = CatRLib.ThetaEst(it_given, x, paramModel.EnumToString(), method: "ML"); // Call "KL" function from CS double cs_KL = CatRLib.KL(itemBank, 1, x, it_given, paramModel.EnumToString(), theta: th_est); if (r_KL[0] - cs_KL > testEpsilon) { resultFlag = false; } Assert.IsTrue(resultFlag); }
// Pi method for Polytomous Items public static PiListPoly Pi_Poly_Calc(double th, CATItems it, string model, double D) { PiListPoly objPi = null; double[,] prov = null, prov1 = null, prov2 = null, prov3 = null; try { if (!String.IsNullOrEmpty(model)) { ModelNames.Models model_Name = ModelNames.StringToEnum(model); if (model_Name == ModelNames.Models.GRM || model_Name == ModelNames.Models.MGRM) { #region "Variable Declarations" if (model_Name == ModelNames.Models.GRM) { prov = new double[it.NumOfItems, it.colSize]; prov1 = new double[it.NumOfItems, it.colSize]; prov2 = new double[it.NumOfItems, it.colSize]; prov3 = new double[it.NumOfItems, it.colSize]; objPi = new PiListPoly(it.NumOfItems, it.colSize); } if (model_Name == ModelNames.Models.MGRM) { prov = new double[it.NumOfItems, it.colSize - 1]; prov1 = new double[it.NumOfItems, it.colSize - 1]; prov2 = new double[it.NumOfItems, it.colSize - 1]; prov3 = new double[it.NumOfItems, it.colSize - 1]; objPi = new PiListPoly(it.NumOfItems, it.colSize - 1); } #endregion #region "Functional Logic" for (int i = 0; i < it.NumOfItems; i++) // Traversing through items { // "alphaj", 1st column double aj = it.all_items_poly[0][i]; // Calculation of "betaj" vector values double[] bj = null; // "GRM" if (model_Name == ModelNames.Models.GRM) { bj = new double[it.colSize - 1]; // Values starting from 2nd column int b_Index = 1; for (int k = 0; k < bj.Length; k++) { bj[k] = it.all_items_poly[b_Index][i];; b_Index++; } } else // "MGRM" { // "betaj", 2nd column double bj0 = it.all_items_poly[1][i]; bj = new double[it.colSize - 2]; // Values starting from 3rd column int c_Index = 2; for (int k = 0; k < bj.Length; k++) { bj[k] = bj0 - it.all_items_poly[c_Index][i]; c_Index++; } } // Final Array must be NaN value free bj = CheckNaValues.GetArrayWithoutNaN(bj); double[] ej = new double[bj.Length]; double[] Pjs = new double[bj.Length + 2]; double[] dPjs = new double[Pjs.Length]; double[] d2Pjs = new double[Pjs.Length]; double[] d3Pjs = new double[Pjs.Length]; Pjs[0] = 1.000; // 1st Column Pjs[Pjs.Length - 1] = 0.000; // last column for (int m = 0; m < bj.Length; m++) { // Calculation of "ej" ej[m] = Math.Exp(D * aj * (th - bj[m])); // Calculation of "Pjs" Pjs[m + 1] = ej[m] / (1 + ej[m]); } // Calculation of "dPj", "d2Pj", "d3Pj" for (int j = 0; j < Pjs.Length; j++) { dPjs[j] = D * aj * Pjs[j] * (1 - Pjs[j]); d2Pjs[j] = D * aj * (dPjs[j] - 2 * Pjs[j] * dPjs[j]); d3Pjs[j] = D * aj * (d2Pjs[j] - 2 * Math.Pow(dPjs[j], 2) - 2 * Pjs[j] * d2Pjs[j]); } for (int index = 0; index < Pjs.Length - 1; index++) { prov[i, index] = Pjs[index] - Pjs[index + 1]; prov1[i, index] = dPjs[index] - dPjs[index + 1]; prov2[i, index] = d2Pjs[index] - d2Pjs[index + 1]; prov3[i, index] = d3Pjs[index] - d3Pjs[index + 1]; } } #endregion } else if (model_Name == ModelNames.Models.PCM || model_Name == ModelNames.Models.GPCM || model_Name == ModelNames.Models.RSM || model_Name == ModelNames.Models.NRM) { double[] dj = null; double[] v = null; // Common column for the following models if (model_Name == ModelNames.Models.PCM) { #region "Variable Declarations" prov = new double[it.NumOfItems, it.colSize + 1]; prov1 = new double[it.NumOfItems, it.colSize + 1]; prov2 = new double[it.NumOfItems, it.colSize + 1]; prov3 = new double[it.NumOfItems, it.colSize + 1]; objPi = new PiListPoly(it.NumOfItems, it.colSize + 1); #endregion #region "Functional Logic" for (int i = 0; i < it.NumOfItems; i++) { dj = new double[it.colSize + 1]; v = new double[it.colSize + 1]; dj[0] = 0.00; v[0] = 0.00; for (int k = 1; k < dj.Length; k++) { dj[k] = dj[k - 1] + D * (th - it.all_items_poly[k - 1][i]); v[k] = k; } double[][] temp_dj_v = CheckNaValues.GetArrayWithoutNaN(dj, v); dj = temp_dj_v[0]; v = temp_dj_v[1]; calculatePolyPi(dj, prov, prov1, prov2, prov3, v, i); } #endregion } if (model_Name == ModelNames.Models.GPCM) { #region "Variable Declarations" prov = new double[it.NumOfItems, it.colSize]; prov1 = new double[it.NumOfItems, it.colSize]; prov2 = new double[it.NumOfItems, it.colSize]; prov3 = new double[it.NumOfItems, it.colSize]; objPi = new PiListPoly(it.NumOfItems, it.colSize); #endregion #region "Functional Logic" for (int i = 0; i < it.NumOfItems; i++) { // "alphaj", 1st column double aj = it.all_items_poly[0][i]; dj = new double[it.colSize]; v = new double[it.colSize]; dj[0] = 0.00; v[0] = 0.00; for (int k = 1; k < dj.Length; k++) { dj[k] = dj[k - 1] + aj * D * (th - it.all_items_poly[k][i]); v[k] = aj * k; } double[][] temp_dj_v = CheckNaValues.GetArrayWithoutNaN(dj, v); dj = temp_dj_v[0]; v = temp_dj_v[1]; calculatePolyPi(dj, prov, prov1, prov2, prov3, v, i); } #endregion } if (model_Name == ModelNames.Models.RSM) { #region "Variable Declarations" prov = new double[it.NumOfItems, it.colSize]; prov1 = new double[it.NumOfItems, it.colSize]; prov2 = new double[it.NumOfItems, it.colSize]; prov3 = new double[it.NumOfItems, it.colSize]; objPi = new PiListPoly(it.NumOfItems, it.colSize); #endregion #region "Functional Logic" for (int i = 0; i < it.NumOfItems; i++) { // "lambdaj", 1st column double lambdaj = it.all_items_poly[0][i]; dj = new double[it.colSize]; v = new double[it.colSize]; dj[0] = 0.00; v[0] = 0.00; for (int k = 1; k < dj.Length; k++) { dj[k] = dj[k - 1] + D * (th - (lambdaj + it.all_items_poly[k][i])); v[k] = k; } double[][] temp_dj_v = CheckNaValues.GetArrayWithoutNaN(dj, v); dj = temp_dj_v[0]; v = temp_dj_v[1]; calculatePolyPi(dj, prov, prov1, prov2, prov3, v, i); } #endregion } if (model_Name == ModelNames.Models.NRM) { #region "Variable Declarations" int nc = (it.colSize / 2) + 1; prov = new double[it.NumOfItems, nc]; prov1 = new double[it.NumOfItems, nc]; prov2 = new double[it.NumOfItems, nc]; prov3 = new double[it.NumOfItems, nc]; objPi = new PiListPoly(it.NumOfItems, nc); #endregion #region "Functional Logic" for (int i = 0; i < it.NumOfItems; i++) // Row Iteration { dj = new double[nc]; v = new double[nc]; dj[0] = 0.00; v[0] = 0.00; for (int k = 1; k < dj.Length; k++) { dj[k] = it.all_items_poly[2 * (k - 2) + 2][i] * th + it.all_items_poly[2 * (k - 2) + 3][i]; v[k] = it.all_items_poly[2 * (k - 2) + 2][i]; } double[][] temp_dj_v = CheckNaValues.GetArrayWithoutNaN(dj, v); dj = temp_dj_v[0]; v = temp_dj_v[1]; calculatePolyPi(dj, prov, prov1, prov2, prov3, v, i); } #endregion } } else { objPi.Exception = "Polytomous items model not matched!"; } } else { objPi.Exception = "Polytomous model not provided!"; } objPi.Add(prov, prov1, prov2, prov3); //objPi.catDictionaryList = new Dictionary<string, Dictionary<string, catList>>(); //GetCATList(objPi.Pi, objPi.catDictionaryList, "Pi"); //GetCATList(objPi.dPi, objPi.catDictionaryList, "dPi"); //GetCATList(objPi.d2Pi, objPi.catDictionaryList, "d2Pi"); //GetCATList(objPi.d3Pi, objPi.catDictionaryList, "d3Pi"); } catch (Exception ex) { if (ex != null) { if (objPi == null) { objPi = new PiListPoly(); } objPi.Exception = ex.Message; } return(objPi); } return(objPi); }
public static void Main(string[] args) { //f<double[], double> delObj = new f<double[], double>(Method2); //Console.WriteLine(delObj(new double[] {1, 4, 5}).ToString()); ModelNames.Models paramModel = ModelNames.Models.GRM; int NumOfItems = 50; resultFlag = true; var stopwatch = new Stopwatch(); REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Polytomous Items CharacterVector modelName = engineObj.CreateCharacterVector(new string[] { paramModel.EnumToString() }); engineObj.SetSymbol("modelName", modelName); DataFrame PolyItems = engineObj.Evaluate("PolyItems <- genPolyMatrix(" + NumOfItems + ", 5, model = modelName, same.nrCat = TRUE)").AsDataFrame(); engineObj.SetSymbol("PolyItems", PolyItems); // Adapting with the existing "CAT-Items" type (Wrapper) Console.WriteLine("*******************************************"); Console.WriteLine("Polytomous Items, Model : " + paramModel.EnumToString()); Console.WriteLine("*******************************************"); CATItems itemBank = new CATItems(NumOfItems: NumOfItems, model: paramModel.EnumToString(), nrCat: 5); for (int i = 0; i < itemBank.colSize; i++) { itemBank.all_items_poly[i] = PolyItems[i].Select(y => (double)y).ToArray(); } //Creation of a response pattern engineObj.Evaluate("set.seed(1)"); NumericVector x_val = engineObj.Evaluate("x_val <- genPattern(0, PolyItems, model = modelName)").AsNumeric(); engineObj.SetSymbol("x_val", x_val); int[] x = x_val.Select(y => (int)y).ToArray(); Console.WriteLine("Start of R Processing: " + DateTime.Now.TimeOfDay.ToString()); stopwatch.Restart(); // Call "ThetaEST" function from R, method = \"ML\" NumericVector r_ThetaEst = engineObj.Evaluate("r_ThetaEst <- thetaEst(PolyItems, x_val, model = modelName, method = \"BM\", priorDist = \"norm\", priorPar = c(-2, 2))").AsNumeric(); engineObj.SetSymbol("r_ThetaEst", r_ThetaEst); Console.WriteLine("R Time taken: " + stopwatch.ElapsedMilliseconds); Console.WriteLine("R Theta Calculation Finished on: " + DateTime.Now.TimeOfDay.ToString()); double[] priorPar = new double[2]; priorPar[0] = -2; priorPar[1] = 2; Console.WriteLine("Start of CS Processing: " + DateTime.Now.TimeOfDay.ToString()); stopwatch.Restart(); // Call "ThetaEST" function from CS double cs_ThetaEst = CatRLib.ThetaEst(it: itemBank, x: x, method: "BM", model: paramModel.EnumToString(), priorPar: priorPar, priorDist: "norm"); Console.WriteLine("CS Time taken: " + stopwatch.ElapsedMilliseconds); Console.WriteLine("CS Theta Calculation Finished on: " + DateTime.Now.TimeOfDay.ToString()); // Compare result of function "ThetaEst" if (decimal.Round(Convert.ToDecimal(r_ThetaEst[0]), decimalPoint) - decimal.Round(Convert.ToDecimal(cs_ThetaEst), decimalPoint) > decimal.Round(Convert.ToDecimal(testEpsilon), decimalPoint)) { resultFlag = false; } if (resultFlag) { Console.WriteLine("Values matched !!"); } else { Console.WriteLine("Values are not matched !!"); } }
public void testEPV_D() { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Dichotomous Items DataFrame DichoItems = engineObj.Evaluate("DichoItems <- genDichoMatrix(items = 200)").AsDataFrame(); engineObj.SetSymbol("DichoItems", DichoItems); // Adapting with the existing "CAT-Items" type (Wrapper) CATItems itemBank = new CATItems(DichoItems[0].Select(y => (double)y).ToArray(), DichoItems[1].Select(y => (double)y).ToArray(), DichoItems[2].Select(y => (double)y).ToArray(), DichoItems[3].Select(y => (double)y).ToArray()); // test for different theta values double[] th = CatRcs.Utils.CommonHelper.Sequence(-6, 6, length: 11); var stopwatch = new Stopwatch(); stopwatch.Restart(); for (int t = 0; t < th.Length; t++) { string temp = th[t].ToString(nfi); // Dichotomous Items DataFrame it_given_R = engineObj.Evaluate("it_given_R <- DichoItems[c(4, 8),]").AsDataFrame(); engineObj.SetSymbol("it_given_R", it_given_R); //Creation of a response pattern for theta value engineObj.Evaluate("set.seed(1)"); NumericVector x_val = engineObj.Evaluate("x_val <- genPattern(" + th[t].ToString(nfi) + ", it_given_R)").AsNumeric(); engineObj.SetSymbol("x_val", x_val); int[] x = x_val.Select(y => (int)y).ToArray(); int[] index = new int[] { 4, 8 }; CATItems it_given = new CATItems(index.Length); // itemBank.FindItem(new int[] { 4, 8 }); for (int i = 0; i < index.Length; i++) { it_given.a[i] = itemBank.a[index[i] - 1]; it_given.b[i] = itemBank.b[index[i] - 1]; it_given.c[i] = itemBank.c[index[i] - 1]; it_given.d[i] = itemBank.d[index[i] - 1]; } // Call "EPV" function from R NumericVector r_epv = engineObj.Evaluate("r_epv <- EPV(DichoItems, 1, x_val, " + th[t].ToString(nfi) + ", it_given_R)").AsNumeric(); stopwatch.Restart(); // Call "EPV" function from CatRCS double cs_epv = CatRLib.EPV(itemBank, 1, x, th[t], it_given, ""); Console.WriteLine("Time taken: " + stopwatch.ElapsedMilliseconds); if (r_epv[0] - cs_epv > testEpsilon) { resultFlag = false; } Console.WriteLine(r_epv[0] + " " + cs_epv); } Assert.IsTrue(resultFlag); }
public void testPi_D() { bool OSProc = System.Environment.Is64BitProcess; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Dichotomous Items DataFrame DichoItems = engineObj.Evaluate("DichoItems <- genDichoMatrix(items = 100)").AsDataFrame(); engineObj.SetSymbol("DichoItems", DichoItems); // Adapting with the existing "CAT-Items" type (Wrapper) CATItems itemBank = new CATItems(DichoItems[0].Select(y => (double)y).ToArray(), DichoItems[1].Select(y => (double)y).ToArray(), DichoItems[2].Select(y => (double)y).ToArray(), DichoItems[3].Select(y => (double)y).ToArray()); #region "Test block for Ability Values (th)" PiList objPI = null; int decimalPoint = 4; double[] th_Values = CatRcs.Utils.CommonHelper.Sequence(-6, 6, by: 1); Console.WriteLine("******* TEST for Ability value Theta ********"); for (int k = 0; k < th_Values.Length; k++) { // Sequence Generation for Theta (Ability) values NumericVector th_val = engineObj.CreateNumericVector(new double[] { th_Values[k] }); engineObj.SetSymbol("th_val", th_val); // Calling the "Pi" from R GenericVector result_Pi = engineObj.Evaluate("result_Pi <- Pi(th = th_val, DichoItems, D = 1)").AsList(); // Getting the function result NumericVector Pi = result_Pi[0].AsNumeric(); NumericVector dPi = result_Pi[1].AsNumeric(); NumericVector d2Pi = result_Pi[2].AsNumeric(); NumericVector d3Pi = result_Pi[3].AsNumeric(); Console.WriteLine("Value of Theta: " + th_Values[k]); objPI = CatRLib.Pi_D(th_Values[k], itemBank, "", 1); #region "Pi" int z = 0; resultFlag = true; Console.WriteLine("****** Pi ******"); for (int i = 0; i < Pi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(Pi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.Pi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag, "Passed"); Console.WriteLine("Values of Pi are Matched!"); #endregion #region "dPi" z = 0; resultFlag = true; Console.WriteLine("****** dPi ******"); for (int i = 0; i < dPi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(dPi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.dPi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of dPi are Matched!"); #endregion #region "d2Pi" z = 0; resultFlag = true; Console.WriteLine("****** d2Pi ******"); for (int i = 0; i < d2Pi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(d2Pi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.d2Pi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of d2Pi are Matched!"); #endregion #region "d3Pi" z = 0; resultFlag = true; Console.WriteLine("****** d3Pi ******"); for (int i = 0; i < d3Pi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(d3Pi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.d3Pi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of d3Pi are Matched!"); #endregion } Assert.IsTrue(resultFlag); #endregion #region "Test block for Metric values" objPI = null; double[] D_Values = CatRcs.Utils.CommonHelper.Sequence(0.5, 1, by: 0.1); Console.WriteLine("******* TEST for Metric Constant ********"); for (int k = 0; k < D_Values.Length; k++) { // Sequence Generation for Theta (Ability) values NumericVector D_val = engineObj.CreateNumericVector(new double[] { D_Values[k] }); engineObj.SetSymbol("D_val", D_val); // Calling the "Pi" from R GenericVector result_Pi = engineObj.Evaluate("result_Pi <- Pi(th = 0, DichoItems, D = D_val)").AsList(); // Getting the function result NumericVector Pi = result_Pi[0].AsNumeric(); NumericVector dPi = result_Pi[1].AsNumeric(); NumericVector d2Pi = result_Pi[2].AsNumeric(); NumericVector d3Pi = result_Pi[3].AsNumeric(); Console.WriteLine("Value of Metric constant: " + D_Values[k]); objPI = CatRLib.Pi_D(0, itemBank, "", D_Values[k]); #region "Pi" int z = 0; resultFlag = true; Console.WriteLine("****** Pi ******"); for (int i = 0; i < Pi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(Pi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.Pi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of Pi are matched!"); #endregion #region "dPi" z = 0; resultFlag = true; Console.WriteLine("****** dPi ******"); for (int i = 0; i < dPi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(dPi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.dPi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of dPi are matched!"); #endregion #region "d2Pi" z = 0; resultFlag = true; Console.WriteLine("****** d2Pi ******"); for (int i = 0; i < d2Pi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(d2Pi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.d2Pi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of d2Pi are Matched!"); #endregion #region "d3Pi" z = 0; resultFlag = true; Console.WriteLine("****** d3Pi ******"); for (int i = 0; i < d3Pi.Length; i++) { z = i + 1; // item number if (decimal.Round(Convert.ToDecimal(d3Pi[i]), decimalPoint) != decimal.Round(Convert.ToDecimal(objPI.d3Pi[i]), decimalPoint)) { //Console.WriteLine("Test for Item No. # " + z + " is not Passed!"); resultFlag = false; } } Assert.IsTrue(resultFlag); Console.WriteLine("Values of d3Pi are Matched!"); #endregion } #endregion }
public static double MEI_Calc(CATItems itemBank, int item, int[] x, double theta, CATItems it_given, string model = null, string method = "BM", double D = 1, double[] priorPar = null, string priorDist = "norm", double[] range = null, int[] parInt = null, int infoType = 2 /* Observed */) { double res = 0; if (priorPar == null || priorPar.Length < 2) { priorPar = new double[2]; priorPar[0] = 0; priorPar[1] = 1; } if (parInt == null || parInt.Length < 3) { parInt = new int[3]; parInt[0] = -4; parInt[1] = 4; parInt[2] = 33; } if (range == null || range.Length < 2) { range = new double[2]; range[0] = -4; range[1] = 4; } if ((infoType == (int)ModelNames.InfoType.Observed) || (infoType == (int)ModelNames.InfoType.Fisher)) // type is either "Observed" or "Fisher" { double th = theta; // Finding desired "item" from itembank & Added to given items "it_given". // Instead of "itj", "it_given" will be used. itemBank.AddItem(it_given, item); if (String.IsNullOrEmpty(model)) // Dichotomous Items { List <int> temp_x = x.ToList(); temp_x.Add(0); double th0 = CatRcs.ThetaEST.ThetaEst_Calc(it_given, temp_x.ToArray(), D: D, model: model, method: method, priorPar: priorPar, priorDist: priorDist, parInt: parInt, range: range); temp_x = x.ToList(); temp_x.Add(1); double th1 = CatRcs.ThetaEST.ThetaEst_Calc(it_given, temp_x.ToArray(), D: D, model: model, method: method, priorPar: priorPar, priorDist: priorDist, parInt: parInt, range: range); double p1 = CatRcs.Pi.Pi_Calc(th, itemBank.FindItem(item), model, D).Pi.First(); double p0 = 1 - p1; double Ij0 = 0, Ij1 = 0; if ((infoType == (int)ModelNames.InfoType.Fisher)) { Ij0 = CatRcs.Ii.Ii_Calc(th0, itemBank.FindItem(item), model, D).Ii.First(); Ij1 = CatRcs.Ii.Ii_Calc(th1, itemBank.FindItem(item), model, D).Ii.First(); } else { Ij0 = CatRcs.OIi.OIi_Calc(th0, itemBank.FindItem(item), new int[] { 0 }, model, D).OIi.First(); Ij1 = CatRcs.OIi.OIi_Calc(th1, itemBank.FindItem(item), new int[] { 1 }, model, D).OIi.First(); } res = (p0 * Ij0) + (p1 * Ij1); } else // Polytomous Items { double[,] probs = Pi.Pi_Poly_Calc(theta, itemBank.FindItem(item), model, D).Pi; double[] Ii_new = new double[probs.GetLength(1)]; for (int j = 0; j < probs.GetLength(1); j++) // column iteration { List <int> temp_x = x.ToList(); temp_x.Add(j); double th_new = CatRcs.ThetaEST.ThetaEst_Calc(it_given, temp_x.ToArray(), D: D, model: model, method: method, priorPar: priorPar, priorDist: priorDist, parInt: parInt, range: range); if ((infoType == (int)ModelNames.InfoType.Fisher)) { Ii_new[j] = CatRcs.Ii.Ii_Calc(th_new, itemBank.FindItem(item), model, D).Ii.First(); } else { Ii_new[j] = CatRcs.OIi.OIi_Calc(th_new, itemBank.FindItem(item), new int[] { j }, model, D).OIi.First(); } } res = CatRcs.Utils.RowColumn.Sum(Ii_new.ToList().Select((p, i) => p * probs[0, i]).ToArray()); } } else { return(res); } return(res); }
public void testEapEST_and_EapSEM_P(int NumOfItems, ModelNames.Models paramModel) { resultFlag = true; REngine.SetEnvironmentVariables(); REngine engineObj = REngine.GetInstance(); // Loading a library from R engineObj.Evaluate("library(catR)"); // Polytomous Items CharacterVector modelName = engineObj.CreateCharacterVector(new string[] { paramModel.EnumToString() }); engineObj.SetSymbol("modelName", modelName); DataFrame PolyItems = engineObj.Evaluate("PolyItems <- genPolyMatrix(" + NumOfItems + ", 5, model = modelName, same.nrCat = TRUE)").AsDataFrame(); engineObj.SetSymbol("PolyItems", PolyItems); // Adapting with the existing "CAT-Items" type (Wrapper) Console.WriteLine("*******************************************"); Console.WriteLine("Polytomous Items, Model : " + paramModel.EnumToString()); Console.WriteLine("*******************************************"); CATItems itemBank = new CATItems(PolyItems[0].Length, paramModel.EnumToString(), 5); Tuple <CATItems.ColumnNames, int>[] cols = itemBank.GetKeys(); for (int i = 0; i < cols.Length; i++) { itemBank.SetItemParamter(cols[i], PolyItems[i].Select(y => (double)y).ToArray()); } #region "Test block for Ability Values (th)" double[] th = CatRcs.Utils.CommonHelper.Sequence(-6, 6, length: 11); for (int j = 0; j < th.Length; j++) { string temp = th[j].ToString(nfi); //Creation of a response pattern for theta value engineObj.Evaluate("set.seed(1)"); NumericVector x_val = engineObj.Evaluate("x_val <- genPattern(" + "th = " + th[j].ToString(nfi) + ", PolyItems, " + "model = modelName)").AsNumeric(); engineObj.SetSymbol("x_val", x_val); int[] x = x_val.Select(y => (int)y).ToArray(); // Call "EapEST" function from R NumericVector r_eapEst = engineObj.Evaluate("result_Eap <- eapEst(PolyItems, x_val, model = modelName)").AsNumeric(); // Call "EapEST" function from CatRCS double cs_eapEst = CatRLib.EapEST(itemBank, x, paramModel.EnumToString()); /* EapEst function, line 111 needs to be optimized for passing the Test * Check EapSEM function too !! */ // Call "EapSEM" function from R NumericVector r_eapSem = engineObj.Evaluate("result_EapSem <- eapSem(result_Eap, PolyItems, x_val, model = modelName)").AsNumeric(); // Call "EapSEM" function from CatRCS double cs_eapSem = CatRLib.EapSEM(cs_eapEst, itemBank, x, paramModel.EnumToString()); if (r_eapEst[0] - cs_eapEst > testEpsilon || r_eapSem[0] - cs_eapSem > testEpsilon) { resultFlag = false; } } Assert.IsTrue(resultFlag); #endregion }