00001 /*! \file ItemNR.h 00002 00003 \brief 00004 ItemNR class, derived from Item, maintains information calculated for 00005 an Item object in the E-step so that it can be used in the M-step 00006 to estimate item parameters. 00007 00008 Information stored from the E-step includes the expected number of 00009 examinees in each category of the discrete latent variable of those 00010 that took the item (these usually are denoted by the letter "n"), 00011 and for each item response the expected number of examinees in each 00012 category of the discrete latent variable who gave that item response 00013 of those examinees who took the item (these usually are denoted by 00014 the letter "r"). 00015 00016 Estimation Toolkit for Item Response Models (ETIRM) 00017 http://www.smallwaters.com/software/cpp/etirm.html 00018 00019 Author(s): 00020 Werner Wothke, maintenance (http://www.smallwaters.com) 00021 Brad Hanson (http://www.b-a-h.com/) 00022 See the file LICENSE for information on usage and redistribution. 00023 00024 Copyright (C) 2008, Werner Wothke 00025 Copyright (c) 2000-2001, Bradley A. Hanson 00026 */ 00027 00028 #ifndef ETIRM_ITEMNR_H_ 00029 #define ETIRM_ITEMNR_H_ 00030 00031 #ifdef ETIRM_NO_DIR_PREFIX 00032 #include "Item.h" 00033 #else 00034 #include "etirm/Item.h" 00035 #endif 00036 00037 namespace etirm 00038 { 00039 /*! 00040 \brief 00041 Class, derived from Item, to maintain information calculated for 00042 an Item object in the E-step so that it can be used in the M-step 00043 to estimate item parameters. 00044 00045 Information stored from the E-step includes the expected number of 00046 examinees in each category of the discrete latent variable of those 00047 that took the item (these usually are denoted by the letter "n"), 00048 and for each item response the expected number of examinees in each 00049 category of the discrete latent variable who gave that item response 00050 of those examinees who took the item (these usually are denoted by 00051 the letter "r"). 00052 00053 \section template_args Template Parameters 00054 00055 \param D Class for discrete latent variable distribution. 00056 */ 00057 template <class D> class ItemNR : public Item<typename D::latentvar_type> 00058 { 00059 00060 public: 00061 00062 //! Type iterator over responses of an item. 00063 typedef RealMatrix::row_iterator r_iterator; 00064 00065 //! Type iterator over number of examinees who responded to an item. 00066 typedef RealVector::iterator n_iterator; 00067 00068 //! Type iterator over quadrature points. 00069 typedef typename D::point_iterator point_iterator; 00070 00071 /*! 00072 \brief 00073 Constructor. 00074 00075 \section template_args Template Parameters 00076 00077 \param D Class for discrete latent variable distribution. 00078 00079 \section function_args Function Parameters 00080 00081 \param[in] nparam Number of item parameters. 00082 \param[in] index Zero-offset index of item in vector of all item responses. 00083 \param[in] respCat Number of response categories. 00084 \param[in] dist Latent variable distribution. 00085 */ 00086 ItemNR(int nparam, int index, int respCat, D *dist = 0); 00087 00088 //! Destructor. 00089 virtual ~ItemNR(); 00090 00091 /*! 00092 \brief 00093 Returns iterator to first element of row of mR corresponding to response "resp" 00094 for examinee group "group" (where the first examinee group is group 1) 00095 00096 \section function_args Function Parameters 00097 00098 \param[in] resp Response vector. 00099 \param[in] group Examinee group (default =1). 00100 */ 00101 r_iterator RVector(Response resp, int group = 1); 00102 00103 /*! 00104 \brief 00105 Returns iterator to first element of mN for examinee group "group" 00106 (where the first examinee group is group 1). 00107 00108 \section function_args Function Parameters 00109 00110 \param[in] group Group index. 00111 */ 00112 n_iterator NVector(int group = 1); 00113 00114 00115 /*! 00116 \brief 00117 Assigns values associated with discrete latent variable categories. 00118 00119 Note: I was not able to locate any SetLatentVarPoints function in the code base. 00120 It is questionable whether this function is operative at all (ww, 2-28-2008). 00121 00122 \section function_args Function Parameters 00123 00124 \param[in] n Number of discrete categories of the latent ability distribution. 00125 \param[in] points Iterator over quadrature points. 00126 */ 00127 void SetLatentVarPoints(int n, point_iterator points); 00128 00129 /*! 00130 \brief 00131 Returns iterator over quadrature points. 00132 00133 \section function_args Function Parameters 00134 00135 \param[in] group \ Examinee group (1, 2, ..., "number of groups"). 00136 */ 00137 point_iterator GetLatentVarPoints(int group = 1) 00138 { 00139 return mLatentDist->begin_points(group); 00140 } 00141 00142 //! Returns number of discrete latent variable categories. 00143 int NumLatentVarCat() 00144 { 00145 return mNumLatentVarCat; 00146 } 00147 00148 /*! 00149 \brief 00150 Initializes elements of mR and mN to zero. 00151 */ 00152 void InitializeNR(); 00153 00154 /* The following functions provide an interface to minimization routines (such as UNCMIN) 00155 that are used in the M-step to estimates parameters for one item. */ 00156 00157 /*! 00158 \brief 00159 Function to maximize in M-step. 00160 00161 \section function_args Function Parameters 00162 00163 \param[in] &p Address of item parameter vector. 00164 00165 Note: Technically, negative value of function is being minimized, so the negative function 00166 value is being returned. 00167 */ 00168 virtual double f_to_minimize(RealVector &p) = 0; 00169 00170 /*! 00171 \brief 00172 Computes gradient of function to maximize in M-step. 00173 00174 \section function_args Function Parameters 00175 00176 \param[in] &p Address of item parameter vector. 00177 \param[out] &g Address of gradient vector. Gradient values are returned in the vector elements. 00178 00179 Note: Technically, negative value of function is being minimized, so the negative gradient 00180 is being returned. 00181 */ 00182 virtual void gradient(RealVector &p, RealVector &g) = 0; 00183 00184 /*! 00185 \brief 00186 Computes hessian of function to maximize in M-step. 00187 00188 Note: Technically, the negative value of the function is to be minimized by UNCMIN++, 00189 see inline comments in function code. 00190 00191 Note: The hessian is stored in the lower trangle of h. 00192 */ 00193 virtual void hessian(RealVector &x, RealMatrix &h) = 0; 00194 00195 /*! 00196 \brief 00197 Function to indicate that the algebraic gradient of the item (ICCDeriv1) is defined. 00198 00199 This function can be used by UNCMIN++. 00200 */ 00201 virtual int HasAnalyticGradient() const = 0; 00202 00203 /*! 00204 \brief 00205 Function to indicate that the algebraic hessian of the item (ICCDeriv2) is defined. 00206 00207 This function can be used by UNCMIN++. 00208 */ 00209 virtual int HasAnalyticHessian() const = 0; 00210 00211 /*! 00212 \brief 00213 Returns 1 if all parameters have a non-zero prior density, or 0 otherwise. 00214 00215 \section function_args Function Parameters 00216 00217 \param[in] &p Address of parameter vector for this item. 00218 \param[in] ignorePriors Boolan flag to bypass the test of prior densities. 00219 */ 00220 virtual int ValidParameters(const RealVector &p, bool ignorePriors = false) const; 00221 00222 /*! 00223 \brief 00224 Number of item parameters. 00225 */ 00226 int dim() const 00227 { 00228 return Item<typename D::latentvar_type>::NumParameters(); 00229 } // Added "Item<typename D::latentvar_type>::" to NumParameters method call. ww, 1/12/2008 00230 00231 protected: 00232 00233 D *mLatentDist; 00234 //!< Latent variable distribution used to determine discrete categories on the latent variable. 00235 00236 /*! 00237 \brief 00238 Expected number of respondents in each latent variable category 00239 who took this item and gave the i-th response. 00240 00241 If there are different points for different examinee groups 00242 the expected number of examinees will differ for different groups, 00243 and will be stacked in each row. 00244 00245 The first mNumLatentVarCat values will be for the first group, 00246 the second mNumLatentVarCat values will be for the second group, etc. 00247 These expected counts are computed in the E-step. 00248 */ 00249 RealMatrix *mR; 00250 00251 /*! 00252 \brief 00253 Expected number of examinees who took this item in 00254 each latent variable category. 00255 00256 If there are different points for different examinee groups 00257 the expected number of examinees will differ for different groups, 00258 and will be stacked. 00259 00260 The first mNumLatentVarCat values will be for the first group, 00261 the second mNumLatentVarCat values will be for the second group, etc. 00262 These expected counts are computed in the E-step. 00263 */ 00264 RealVector *mN; 00265 00266 00267 int mNumLatentVarCat; 00268 //!< Number of latent variable categories. 00269 00270 }; 00271 00272 /* 00273 \brief 00274 Class constructor. 00275 00276 \section template_args Template Parameters 00277 00278 \param D Class for discrete latent variable distribution. 00279 00280 \section function_args Function Parameters 00281 00282 \param[in] nparam Number of item parameters 00283 \param[in] index Zero-offset index of item in vector of all item responses 00284 \param[in] respCat Number of response categories for item. 00285 \param[in] dist Latent variable distribution used to define discrete 00286 latent variable points. 00287 */ 00288 template <class D> 00289 #ifndef BOOST_MSVC 00290 ItemNR<D>::ItemNR(int nparam, int index, int respCat, D *dist) : 00291 Item<typename D::latentvar_type>(nparam, index, respCat), 00292 #else 00293 ItemNR<D>::ItemNR(int nparam, int index, int respCat, D *dist) : Item<D::latentvar_type>(nparam, index, respCat), 00294 #endif 00295 mLatentDist(dist), mR(0), mN(0), mNumLatentVarCat(0) 00296 { 00297 if (dist) 00298 { 00299 mNumLatentVarCat = dist->size(); 00300 // Compute total number of latent distribution points over all groups for 00301 // which the points are unique 00302 int totpoints = mLatentDist->NumGroupsUnique() * mNumLatentVarCat; 00303 00304 mR = new RealMatrix(respCat, totpoints); 00305 mN = new RealVector(totpoints); 00306 } 00307 } 00308 00309 /* 00310 \brief 00311 Class destructor. 00312 */ 00313 template <class D> ItemNR<D>::~ItemNR() 00314 { 00315 if (mN) 00316 delete mN; 00317 if (mR) 00318 delete mR; 00319 } 00320 00321 /* 00322 \brief 00323 Initializes elements of mR and mN to zero. 00324 */ 00325 template <class D> void ItemNR<D>::InitializeNR() 00326 { 00327 if (mN) 00328 *mN = 0.0; 00329 if (mR) 00330 *mR = 0.0; 00331 } 00332 00333 /* 00334 \brief 00335 Returns iterator to first element of row of mR corresponding to response "resp" 00336 for examinee group "group" (where the first examinee group is group 1) 00337 00338 \section function_args Function Parameters 00339 00340 \param[in] resp Response vector. 00341 \param[in] group Examinee group. 00342 */ 00343 template <class D> typename ItemNR<D>::r_iterator ItemNR<D>::RVector(Response resp, int group) 00344 { 00345 int ngroups = mLatentDist->NumGroups(); 00346 if (group > ngroups || group < 1) 00347 throw InvalidArgument("Invalid group", "ItemNR::RVector"); 00348 00349 r_iterator rvec = mR->begin_row(Item<typename D::latentvar_type>::ResponseIndex(resp)+1); // Added "Item<typename D::latentvar_type>::" to ResponseIndex method call. ww, 1/12/2008 00350 00351 return (mLatentDist->NumGroupsUnique() == 1) ? rvec : (rvec + (group-1) * mNumLatentVarCat); 00352 } 00353 00354 /* 00355 \brief 00356 Returns iterator to first element of mN for examinee group "group" 00357 (where the first examinee group is group 1). 00358 00359 \section function_args Function Parameters 00360 00361 \param[in] group Group index. 00362 */ 00363 template <class D> typename ItemNR<D>::n_iterator ItemNR<D>::NVector(int group) 00364 { 00365 int ngroups = mLatentDist->NumGroups(); 00366 if (group > ngroups || group < 1) 00367 throw InvalidArgument("Invalid group", "ItemNR::NVector"); 00368 00369 n_iterator nvec = mN->begin(); 00370 return (mLatentDist->NumGroupsUnique() == 1) ? nvec : (nvec + (group-1) * mNumLatentVarCat); 00371 } 00372 00373 /* 00374 \brief 00375 Returns 1 if all parameters have a non-zero prior density, or 0 otherwise. 00376 00377 \section function_args Function Parameters 00378 00379 \param[in] ¶m Address of parameter vector for this item. 00380 \param[in] ignorePriors Boolan flag to bypass the test of prior densities. 00381 */ 00382 template <class D> int ItemNR<D>::ValidParameters(const RealVector ¶m, bool ignorePriors) const 00383 { 00384 // For each parameter check that prior density at the value of the 00385 // parameter is not zero 00386 if (!ignorePriors) 00387 { 00388 PriorVector::const_iterator iprior = Item<typename D::latentvar_type>::mPriors.begin(); 00389 RealVector::const_iterator iparam = param.begin(); 00390 for (int i=Item<typename D::latentvar_type>::NumParameters(); i--; ++iprior, ++iparam) // Added "Item<typename D::latentvar_type>::" to NumParameters method call. ww, 1/12/2008 00391 { 00392 if (*iprior) 00393 { 00394 if ((*iprior)->ZeroDensity(*iparam)) 00395 { 00396 return 0; 00397 } 00398 } 00399 } 00400 } 00401 return 1; 00402 } 00403 00404 } // namespace etirm 00405 00406 #endif // ETIRM_ITEMNR_H_