C:/programs/etirm/src/ICRF_PCM.cpp

Go to the documentation of this file.
00001 /*! \file ICRF_PCM.cpp
00002   
00003   \brief
00004   Class for computing item category response function (ICRF) 
00005   and its derivative for the partial credit model.
00006 
00007   Estimation Toolkit for Item Response Models (ETIRM)
00008   http://www.smallwaters.com/software/cpp/etirm.html
00009 
00010   Author(s): 
00011   Werner Wothke, maintenance (http://www.smallwaters.com)
00012   Brad Hanson (http://www.b-a-h.com/)
00013   See the file LICENSE for information on usage and redistribution.
00014 
00015   Copyright (C) 2008, Werner Wothke
00016   Copyright (c) 2000-2002, Bradley A. Hanson
00017 */
00018 
00019 #ifdef ETIRM_NO_DIR_PREFIX
00020 #include "ICRF_PCM.h"
00021 #else
00022 #include "etirm/ICRF_PCM.h"
00023 #endif
00024 
00025 #include <cmath> // for exp
00026 
00027 #if defined(ETIRM_USE_BOOST_CONFIG) || defined(BOOST_NO_LIMITS)
00028 // If no <limits> header use Boost (http://www.boost.org)
00029 // workaround. This assumes the Boost library is available.
00030 #include <boost/detail/limits.hpp>
00031 #else
00032 #include <limits>
00033 #endif
00034 
00035 #ifdef BOOST_NO_STDC_NAMESPACE
00036 // for compilers which do not put C library functions in std namespace
00037 namespace std {using ::exp;}
00038 #endif
00039 
00040 namespace etirm 
00041 {
00042 
00043 /*!
00044   ICRF_PCM::ICRF
00045 
00046   \brief
00047   Computes probability of a response in response category
00048   'r' for latent variable value theta.
00049   
00050   \param[in] r  Response category, where a response in the first
00051       response category is mFirstResponse, the response
00052       in the second response category is mFirstResponse+1,
00053       etc.
00054   \param[in] param  Vector containing item parameters.
00055   \param[in] theta  Latent variable value for which probability is calculated.
00056   
00057 */
00058 Real ICRF_PCM::ICRF(Response r, const RealVector &param, Real theta) const
00059 {
00060   
00061   Real z = 0.0;
00062   Real num = (r == mFirstResponse) ? 1.0 : -1.0;
00063   Real sum = 1.0;
00064   Real a = mA;
00065   Response ir = mFirstResponse+1;
00066   RealVector::const_iterator ip = param.begin();
00067   for (int i = mNumCat-1; i--; ++ir, ++ip)
00068   {
00069     z += a * (theta - *ip);
00070     Real ez = std::exp(z);
00071     if (ir == r) num = ez;
00072     
00073     sum += ez;
00074   }
00075   
00076   return num/sum;
00077 
00078 }
00079 
00080 /*! OpenICRF
00081   
00082   \brief
00083   Computes probability of a correct response for latent
00084   variable value theta, where probability must be in the
00085   open interval (0, 1). This function can be used when the 
00086   logarithm of the probability or logit of the probability
00087   needs to be taken.
00088   
00089 */
00090 Real ICRF_PCM::OpenICRF(Response r, const RealVector &param, Real theta) const
00091 {
00092   
00093   double prob = ICRF(r, param, theta);
00094   
00095   /* Make sure probability is between 0 and 1 */
00096   if (prob <= 0.0)
00097   {
00098     prob = std::numeric_limits<Real>::min();
00099   }
00100   else if (prob >= 1.0)
00101   {
00102     prob = 1.0 - std::numeric_limits<Real>::epsilon();
00103   }
00104 
00105   return prob;
00106 }
00107 
00108 /*! ExpZ
00109   \brief
00110   Computes the terms exp(sum_{k=1}^i z_k), i = 1, mNumCat-1, where
00111   z_k = a * (theta - b_k), a = mA, b_k = param[k-1].
00112   These terms are stored in the data member mExpz.
00113   Also store values in data members mDenom and mDenom2.
00114 */
00115 void ICRF_PCM::ExpZ(const RealVector &param, Real theta)
00116 {
00117   Real a = mA;
00118   
00119   
00120   mExpz[0] = 1.0;
00121   mDenom = 1.0;
00122   RealVector::iterator ie = mExpz.begin()+1;
00123   RealVector::const_iterator ip = param.begin();
00124   Real num = 0.0;
00125   for (int i = mNumCat-1; i--; ++ip, ++ie)
00126   {
00127     num += a * (theta - *ip);
00128     *ie = std::exp(num);
00129     mDenom += *ie;
00130   }
00131   
00132   mDenom2 = mDenom * mDenom;
00133 }
00134 
00135 /*!
00136   ICRFDeriv1
00137   
00138   \brief
00139   Computes first derivatives of ICRF with respect to all parameters.
00140   
00141   Returns derivative with respect to item parameters in
00142   vector deriv.
00143   
00144   The derivative is obtained by computing the derivative of the numerator and
00145   denominator of the ICRF probability separately, and using the formula
00146   for the derivative of a quotient of functions.
00147   
00148 */
00149 void ICRF_PCM::ICRFDeriv1(Response r, const RealVector &param, Real theta, RealVector &deriv)
00150 {
00151   ExpZ(param, theta);
00152   
00153   Real probnum = mExpz[r - mFirstResponse]; // numerator of ICRF for this response
00154   Real a = mA;
00155   
00156   
00157   /* Derivatives with respect to b's. Compute derivative of parameter associated with
00158      the last response category first and work backward. */
00159   RealVector::const_iterator ie = mExpz.begin()+mNumCat-1;
00160   RealVector::iterator id = deriv.begin() + mNumCat-2;
00161   Real dderiv = 0.0;
00162   Real nderiv = -a * probnum;
00163   Response ir = mFirstResponse + mNumCat - 1;
00164   for (int i = mNumCat-1; i--; --ir, --ie, --id)
00165   {
00166     dderiv += -a * *ie;
00167     
00168     if (ir <= r) *id = nderiv * mDenom;
00169     else *id = 0.0;
00170     *id -= probnum * dderiv;
00171     *id /= mDenom2;
00172   }
00173   
00174 }
00175 
00176 /*!
00177   \brief
00178   Transforms item parameters to new IRT scale
00179 */
00180 void ICRF_PCM::Scale(Real slope, Real intercept, RealVector &param)
00181 {
00182 
00183   /* Transform intercept parameters */
00184   RealVector::iterator ip = param.begin();
00185   for (int i = mNumParameters-1; i--; ++ip)
00186   {
00187     *ip *= slope;
00188     *ip += intercept;
00189   }
00190 }
00191 
00192 /*! GetAllParameters
00193  * 
00194   \brief
00195   Takes estimate parameters (b1, b2, ...) as input, outputs allParam, the vector made up
00196   of fixed parameter a, and the estimated parameters b1, b2, ...
00197  */
00198 void ICRF_PCM::GetAllParameters(const RealVector &estParam, RealVector &allParam) const
00199 {
00200   if (estParam.size() != mNumParameters || allParam.size() != mNumParameters+1)
00201   {
00202     throw InvalidArgument("Invalid number of parameters", "ICRF_PCM::GetAllParameters");
00203   }
00204   
00205   allParam[0] = mA;
00206   RealVector::iterator ia = allParam.begin() + 1;
00207   RealVector::const_iterator ie = estParam.begin();
00208   for (int i = mNumParameters; i--; ++ia, ++ie)
00209   {
00210     *ia = *ie;
00211   }
00212 }
00213 
00214 
00215 
00216 
00217 } // namespace etirm

Generated on Sat Mar 1 21:40:15 2008 for ETIRM by  doxygen 1.5.4