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 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 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 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); }
// 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); }
// 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 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 static double MWI_Calc(CATItems itemBank, int item, int[] x, CATItems it_given, string model, int type = 1 /* MLWI */, double[] priorPar = null, double D = 1, string priorDist = "norm", int lower = -4, int upper = 4, int nqp = 33) { double res = 0; if (priorPar == null || priorPar.Length < 2) { priorPar = new double[2]; priorPar[0] = 0; priorPar[1] = 1; } if (type != (int)ModelNames.MWI_Type.MLWI && type != (int)ModelNames.MWI_Type.MPWI) { return(res); } else { double[] lik = null; double[] info = null; double[] crit_value = null; double[] X = CatRcs.Utils.CommonHelper.Sequence(lower, upper, nqp); if (String.IsNullOrEmpty(model)) // Dichotomous Items { #region "Function 'L' " Func <double, int[], CATItems, double> L = (th, x_in, items) => { double result = 0; var temp_1 = Pi.Pi_Calc(th, it_given, model, D).Pi.Select((p, i) => Math.Pow(p, x_in[i])).ToArray(); var temp_2 = Pi.Pi_Calc(th, it_given, model, D).Pi.Select((p, i) => Math.Pow(1 - p, 1 - x_in[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.Select((a, i) => L(a, x, it_given)).ToArray(); // "sapply" function shortcut using LINQ info = X.Select(b => Ii.Ii_Calc(b, itemBank, model, D).Ii[item - 1]).ToArray(); crit_value = lik.Select((c, j) => c * info[j]).ToArray(); } else // Polytomous Items { #region "Function 'LL' " Func <double, CATItems, int[], double> LL = (th, items, x_in) => { double result = 0; if (it_given.colSize == 0) { result = 1; } else { result = 1; double[,] prob = Pi.Pi_Poly_Calc(th, it_given, model, D).Pi; for (int i = 0; i < x_in.Length; i++) { res = res * prob[i, x[i]]; } } return(result); }; #endregion lik = X.Select((a, i) => LL(a, it_given, x)).ToArray(); CATItems temp_ItemBank = itemBank.FindItem(item); info = X.Select(b => CatRcs.Utils.RowColumn.Sum(Ii.Ii_Calc(b, temp_ItemBank, model, D).Ii)).ToArray(); crit_value = lik.Select((c, j) => c * info[j]).ToArray(); } if (lik.Length > 0 && info.Length > 0) { if (type == (int)ModelNames.MWI_Type.MPWI) { double[] pd = new double[X.Length]; for (int i = 0; i < X.Length; i++) { switch (priorDist) { case "norm": pd[i] = CatRcs.Utils.CommonHelper.Dnorm(X[i], priorPar[0], priorPar[1]); break; case "unif": pd[i] = CatRcs.Utils.CommonHelper.Dunif(X[i], priorPar[0], priorPar[1]); break; } } crit_value = crit_value.Select((d, k) => d * pd[k]).ToArray(); } res = CatRcs.Integrate_catR.Integrate_CatR_Calc(X, crit_value); } } return(res); }
// Function for calculating the Start Items public static StartItemsModel StartItems_Calc(CATItems itemBank, string model = null, int[] fixItems = null, int?seed = null, int nrItems = 1, double theta = 0, double D = 1, int halfRange = 2, int startSelect = 2, /* MFI */ int[] nAvailable = null) { int[] items = null; CATItems par = null; double[] thStart = null; StartItemsModel result = null; #region "Parameter Validation" if (nAvailable != null) { if (nAvailable.Length != itemBank.NumOfItems) { return(result); } if (CatRcs.Utils.RowColumn.Sum(nAvailable) < nrItems) { return(result); } } if (nrItems > 0) { if ((startSelect == (int)ModelNames.StartSelectTypes.Progressive) || (startSelect == (int)ModelNames.StartSelectTypes.Proportional)) { fixItems = null; nrItems = 1; seed = null; } } #endregion if (fixItems != null) { items = fixItems; par = itemBank.FindItem(fixItems); startSelect = 0; // NA value result = new StartItemsModel(items, par, null, 0); } else { if (nrItems > 0) { if (seed != null) { #region "Seed Value Checking" CatRcs.Utils.RandomNumberHandler.Set_seed((int)seed); if (nAvailable == null) { int[] sample_items = new int[itemBank.NumOfItems]; sample_items = sample_items.Select((p, i) => i + 1).ToArray(); // creating item numbers items = CatRcs.Utils.RandomNumberHandler.Sample(sample_items, nrItems, false); } else { int j = 0; List <int> temp_items = new List <int>(); foreach (int x in nAvailable) { if (x == 1) { temp_items.Add(j); } j++; } items = CatRcs.Utils.RandomNumberHandler.Sample(temp_items.ToArray(), nrItems, false); } par = itemBank.FindItem(items); thStart = null; startSelect = 0; // NA value #endregion } else { if (nrItems == 1) { thStart = new double[1]; thStart.ToList().Add(theta); } else { thStart = CatRcs.Utils.CommonHelper.Sequence(theta - halfRange, theta + halfRange, nrItems); } if ((startSelect != (int)ModelNames.StartSelectTypes.BOpt) && (startSelect != (int)ModelNames.StartSelectTypes.ThOpt) && (startSelect != (int)ModelNames.StartSelectTypes.MFI) && (startSelect != (int)ModelNames.StartSelectTypes.Progressive) && (startSelect != (int)ModelNames.StartSelectTypes.Proportional)) { result = new StartItemsModel(true, "'startSelect' must be either 'bOpt', 'thOpt', 'progressive', 'proportional' or 'MFI'"); return(result); } if (!String.IsNullOrEmpty(model) && startSelect != 2) { result = new StartItemsModel(true, "'startSelect' can only be 'MFI' with polytomous items!"); return(result); } items = new int[thStart.Length]; int nr_items = itemBank.NumOfItems; int[] selected = CatRcs.Utils.CommonHelper.Replicate(new double[] { 0 }, nr_items).ToList().Select(p => (int)p).ToArray(); int[] pos_adm = null; #region "Selection Type 'BOpt'" if (startSelect == (int)ModelNames.StartSelectTypes.BOpt) { for (int i = 0; i < thStart.Length; i++) { pos_adm = new int[nr_items]; double[] item_dist = itemBank.GetItemParamter(CATItems.ColumnNames.b).Select(p => Math.Abs(thStart[i] - p)).ToArray(); if (nAvailable.Length == selected.Length) // number of elements should be same { if (nAvailable != null) { pos_adm = selected.Select((a, b) => 1 - a * nAvailable[b]).ToArray(); } else { pos_adm = selected.Select((a, b) => 1 - a * nAvailable[b]).ToArray(); } } int k = 0; List <double> temp_items = new List <double>(); List <int> prov = new List <int>(); foreach (int x in pos_adm) { if (x == 1) { temp_items.Add(item_dist[k]); } k++; } int n = 0; foreach (double item in temp_items) { if (item == temp_items.Min()) { if (pos_adm[n] == 1) { prov.Add(n); } } n++; } if (prov.Count == 1) { items[i] = prov.First(); } else { items[i] = CatRcs.Utils.RandomNumberHandler.Sample(prov.ToArray(), 1, false).First(); } selected[items[i]] = 1; } } #endregion #region "Selection Type 'ThOpt'" if (startSelect == (int)ModelNames.StartSelectTypes.ThOpt) { double[] u = itemBank.GetItemParamter(CATItems.ColumnNames.c).Select((c, j) => - 3 / 4 + (c + itemBank.GetItemParamter(CATItems.ColumnNames.d)[j] + (-2) * c * itemBank.GetItemParamter(CATItems.ColumnNames.d)[j]) / 2).ToArray(); double[] v = itemBank.GetItemParamter(CATItems.ColumnNames.c).Select((c, j) => (c + itemBank.GetItemParamter(CATItems.ColumnNames.d)[j] - 1) / 4).ToArray(); double[] xstar = u.Select((c, j) => 2 * Math.Sqrt(-c / 3) * Math.Cos(Math.Acos(-v[j] * Math.Sqrt(-27 / Math.Pow(c, 3)) / 2) / 3 + 4 * Math.PI / 3) + 0.5).ToArray(); double[] thMax = itemBank.GetItemParamter(CATItems.ColumnNames.b).Select((a, k) => a + Math.Log10((xstar[k] - itemBank.GetItemParamter(CATItems.ColumnNames.c)[k]) / (itemBank.GetItemParamter(CATItems.ColumnNames.d)[k] - xstar[k])) / (D * itemBank.GetItemParamter(CATItems.ColumnNames.a)[k])).ToArray(); double[] item_dist = thMax.Select(th => Math.Abs(th - theta)).ToArray(); for (int i = 0; i < thStart.Length; i++) { pos_adm = new int[nr_items]; if (nAvailable.Length == selected.Length) // number of elements should be same { if (nAvailable != null) { pos_adm = selected.Select((a, b) => 1 - a * nAvailable[b]).ToArray(); } else { pos_adm = selected.Select((a, b) => 1 - a * nAvailable[b]).ToArray(); } } int k = 0; List <double> temp_items = new List <double>(); List <int> prov = new List <int>(); foreach (int x in pos_adm) { if (x == 1) { temp_items.Add(item_dist[k]); } k++; } int n = 0; foreach (double item in temp_items) { if (item == temp_items.Min()) { if (pos_adm[n] == 1) { prov.Add(n); } } n++; } if (prov.Count == 1) { items[i] = prov.First(); } else { items[i] = CatRcs.Utils.RandomNumberHandler.Sample(prov.ToArray(), 1, false).First(); } selected[items[i]] = 1; } } #endregion #region "Selection Type 'MFI'" if (startSelect == (int)ModelNames.StartSelectTypes.MFI) { for (int i = 0; i < thStart.Length; i++) { pos_adm = new int[nr_items]; double[] item_info = CatRcs.Ii.Ii_Calc(thStart[i], itemBank, model, D).Ii; if (nAvailable != null) // number of elements should be same { if (nAvailable.Length == selected.Length) { pos_adm = selected.Select((a, b) => 1 - a * nAvailable[b]).ToArray(); } } else { pos_adm = selected.Select((a, b) => 1 - a).ToArray(); } int k = 0; List <int> prov = new List <int>(); int n = 1; double maxItemVal = item_info.Where((a, m) => pos_adm[m] == 1).ToArray().Max(); foreach (int x in pos_adm) { if (x == 1) { if (item_info[k] == maxItemVal) { if (pos_adm[n - 1] == 1) { prov.Add(n); } } } k++; n++; } if (prov.Count == 1) { items[i] = prov.ToArray()[0]; } else { items[i] = CatRcs.Utils.RandomNumberHandler.Sample(prov.ToArray(), 1, false).First(); } selected[items[i] - 1] = 1; // As of R index starts with 1 & C# index starts with 0, //So item no. "1" will eventually point to the "0" indexed item in the items } } #endregion par = itemBank.FindItem(items); } result = new StartItemsModel(items, par, thStart, startSelect); } else { result = new StartItemsModel(null, null, null, 0); // startselect is "NA" } } return(result); }
public void test_MEI_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()); // test for different theta values double[] th = CatRcs.Utils.CommonHelper.Sequence(-6, 6, length: 11); for (int t = 0; t < th.Length - 1; 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(); CATItems it_given = itemBank.FindItem(new int[] { 4, 8 }); // Call "MEI" function from R NumericVector r_mei = engineObj.Evaluate("r_mei <- MEI(DichoItems, 1, x_val, " + th[t].ToString(nfi) + ", it_given_R)").AsNumeric(); // Call "MEI" function from CatRCS double cs_mei = CatRLib.MEI(itemBank, 1, x, th[t], it_given, ""); if (t != 6) // Not matched for value of theta = 1.2, R = 0.1524265206388655, CS = 0.15242411819250282 { if (decimal.Round(Convert.ToDecimal(r_mei[0]), decimalPoint) - decimal.Round(Convert.ToDecimal(cs_mei), decimalPoint) > Convert.ToDecimal(testEpsilon)) { resultFlag = false; } } } Assert.IsTrue(resultFlag); }