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

Go to the documentation of this file.
00001 /*! \file ICCLogistic.cpp
00002 
00003   \brief 
00004   ICCLogistic class for computing item characteristic curve (ICC) of 1, 
00005   2, and 3-parameter logistic models, as well as first and second derivatives of 
00006   ICC.
00007 
00008   Estimation Toolkit for Item Response Models (ETIRM) 
00009   http://www.smallwaters.com/software/cpp/etirm.html
00010 
00011   Author(s): 
00012   Werner Wothke, maintenance (http://www.smallwaters.com)
00013   Brad Hanson (http://www.b-a-h.com/)
00014   See the file LICENSE for information on usage and redistribution.
00015 
00016   Copyright (C) 2008, Werner Wothke
00017   Copyright (c) 2000-2002, Bradley A. Hanson
00018  */
00019 
00020 #ifdef ETIRM_NO_DIR_PREFIX 
00021 #include "ICCLogistic.h" 
00022 #else 
00023 #include 
00024 "etirm/ICCLogistic.h"
00025 #endif
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 #include <cmath> // for exp
00036 // for compilers which do not put C library functions in std namespace 
00037 #ifdef BOOST_NO_STDC_NAMESPACE 
00038 namespace std
00039 { using ::exp;}
00040 #endif
00041 
00042 namespace etirm
00043 {
00044 
00045   /*
00046     \brief
00047     Returns the probability of a correct response for the 3PL item with parameters 
00048     a, b, c, and ability value theta.
00049     
00050     \section function_args Function Parameters
00051  
00052     \param[in]  a Item slope parameter.
00053     \param[in]  b Item location parameter.
00054     \param[in]  c Item pseudo-guessing parameter.
00055     \param[in]  theta Examinee ability parameter.
00056    */
00057   Real ICC3PLFunc::ICC3PL(Real a, Real b, Real c, Real theta) const
00058   {
00059 
00060     Real prob = std::exp(-mD * a * (theta - b));
00061     prob += 1.0;
00062     prob = (1.0-c) / prob;
00063     prob += c;
00064 
00065     return prob;
00066   }
00067 
00068   /*
00069     \brief
00070     Returns the probability in the open interval (0, 1) of a correct response for 
00071     the 3PL item with parameters a, b, c, and ability value theta.
00072     
00073     This function can be used when the logarithm of the probability or logit of 
00074     the probability needs to be taken.
00075 
00076     \section function_args Function Parameters
00077  
00078     \param[in]  a Item slope parameter.
00079     \param[in]  b Item location parameter.
00080     \param[in]  c Item pseudo-guessing parameter.
00081     \param[in]  theta Examinee ability parameter.
00082    */
00083   Real ICC3PLFunc::OpenICC3PL(Real a, Real b, Real c, Real theta) const
00084   {
00085     double prob = ICC3PL(a, b, c, theta);
00086 
00087     /* Make sure probability is between 0 and 1 */
00088     if (prob <= 0.0)
00089     {
00090       prob = std::numeric_limits<Real>::min();
00091     }
00092     else if (prob >= 1.0)
00093     {
00094       prob = 1.0 - std::numeric_limits<Real>::epsilon();
00095     }
00096     return prob;
00097   }
00098 
00099   /*
00100     \brief
00101     Computes (gradient) vector of first partial derivatives of the 3PL model with respect to item parameters.
00102     
00103     Returns results in deriv vector.
00104 
00105     \section function_args Function Parameters
00106 
00107     \param[in]  numParam Number of parameters (1, 2, or 3) of Logistic IRT model.   
00108     \param[in]  a Item slope parameter.
00109     \param[in]  b Item location parameter.
00110     \param[in]  c Item pseudo-guessing parameter.
00111     \param[in]  theta Examinee ability parameter.
00112     \param[out] &deriv  Address of gradient vector of length numParam. 
00113    */
00114   void ICC3PLFunc::ICC3PLDeriv1(int numParam, Real a, Real b, Real c, Real theta, RealVector &deriv) const
00115   {
00116     Real t = std::exp(-a*mD * (theta - b));
00117     Real onept2 = 1.0 + t;
00118     onept2 *= onept2;
00119 
00120     // derivative with respect to the b parameter   
00121     Real derivb = -a * (1.0 -c) * mD * t;
00122     derivb /= onept2;
00123 
00124     if (numParam == 1)
00125     {
00126       deriv(1) = derivb;
00127       return;
00128     }
00129 
00130     deriv(2) = derivb;
00131 
00132     // derivative with respect to the a parameter   
00133     deriv(1) = (1.0 - c) * (theta - b) * mD * t;
00134     deriv(1) /= onept2;
00135 
00136     // derivative with respect to the c parameter   
00137     if (numParam == 3)
00138     {
00139       deriv(3) = - 1.0 / (1.0 + t);
00140       deriv(3) += 1.0;
00141     }
00142   }
00143 
00144   /*!
00145     \brief
00146     Computes (hessian) matrix of second partial derivatives of the 3PL model with respect to item parameters.
00147     
00148     Returns results in deriv matrix.
00149 
00150     \section function_args Function Parameters
00151 
00152     \param[in]  numParam Number of parameters (1, 2, or 3) of Logistic IRT model.   
00153     \param[in]  a Item slope parameter.
00154     \param[in]  b Item location parameter.
00155     \param[in]  c Item pseudo-guessing parameter.
00156     \param[in]  theta Examinee ability parameter.
00157     \param[out] &deriv  Address of hessian matrix of dimension numParam. Only the lower half and diagonal 
00158         of the matrix are populated, the upper off-diagonal entries remain undefined.
00159    */
00160   void ICC3PLFunc::ICC3PLDeriv2(int numParam, Real a, Real b, Real c, Real theta, RealMatrix &deriv) const
00161   {
00162 
00163     Real e = std::exp(a*mD * (theta - b));
00164     Real onepe3 = 1.0 + e;
00165     Real onepe2 = onepe3 * onepe3;
00166     onepe3 *= onepe2;
00167     Real d2 = mD * mD;
00168     Real cm1 = c - 1.0;
00169     Real em1 = e - 1.0;
00170 
00171     // second derivative with respect to the b parameter  
00172     Real derivt = a * a;
00173     derivt *= cm1 * d2;
00174     derivt *= e * em1;
00175     derivt /= onepe3;
00176 
00177     if (numParam == 1)
00178     {
00179       deriv(1, 1) = derivt;
00180       return;
00181     }
00182 
00183     deriv(2, 2) = derivt;
00184 
00185     Real bmt = b - theta;
00186 
00187     // second derivative with respect to the a parameter  
00188     derivt = cm1 * d2;
00189     derivt *= e * em1;
00190     derivt *= bmt * bmt;
00191     deriv(1, 1) = derivt / onepe3;
00192 
00193     // second derivative with respect to a and b 
00194     Real t2 = 1 + e;
00195     t2 += a * mD * em1 * bmt;
00196     derivt = t2 * cm1;
00197     derivt *= mD * e;
00198     deriv(2, 1) = derivt / onepe3;
00199 
00200     if (numParam == 3)
00201     { // second derivative with respect to the c parameter 
00202       deriv(3, 3) = 0.0;
00203 
00204       Real einv = 1.0 / e;
00205       Real onepeinv2 = 1.0 + einv;
00206       onepeinv2 *= onepeinv2;
00207 
00208       // second derivative with respect to a and c    
00209       derivt = mD * einv;
00210       derivt *= bmt;
00211       deriv(3, 1) = derivt / onepeinv2;
00212 
00213       // second derivative with respect to b and c    
00214       derivt = a * mD * einv;
00215       deriv(3, 2) = derivt / onepeinv2;
00216     }
00217   }
00218 
00219   /*! Constructor for three-parameter logistic ICC object */
00220   ICCLogistic<3>::ICCLogistic(Real D) :
00221     ICC3PLFunc(3, D)
00222   {
00223   }
00224 
00225   /*! Constructor for two-parameter logistic ICC object */
00226   ICCLogistic<2>::ICCLogistic(Real D, Real c) :
00227     ICC3PLFunc(2, D)
00228   {
00229     if (c < 0.0 || c> 1.0)throw InvalidArgument("Invalid c parameter",
00230         "ICCLogistic<2>::ICCLogistic");
00231     fixedC = c;
00232   }
00233 
00234   /*! Constructor for one-parameter logistic ICC object */
00235   ICCLogistic<1>::ICCLogistic(Real D, Real a, Real c) :
00236   ICC3PLFunc(1, D)
00237   {
00238     if (c < 0.0 || c> 1.0)throw InvalidArgument("Invalid c parameter",
00239         "ICCLogistic<1>::ICCLogistic");
00240 
00241     fixedC = c; fixedA = a;}
00242 
00243   //! Method to return allParam for 3PL item 
00244   void ICCLogistic<3>::GetAllParameters(const RealVector &estParam,
00245       RealVector &allParam) const
00246   {
00247     allParam = estParam;
00248   }
00249 
00250   /*! Method to return allParam for 2PL item (estParam contains estimated 
00251    parameters a and b, allParam is assigned to contain a, b, c). */
00252   void ICCLogistic<2>::GetAllParameters(const RealVector &estParam,
00253       RealVector &allParam) const
00254   {
00255     if (estParam.size() != 2 || allParam.size() != 3)
00256     {
00257       throw
00258       InvalidArgument("Invalid number of parameters",
00259           "ICCLogistic<2>::GetAllParameters");
00260     }
00261     allParam[0] = estParam[0];
00262     allParam[1] = estParam[1];
00263     allParam[2] = fixedC;
00264   }
00265 
00266   /*! Method to return allParam for 1PL item (estparam contains estimated 
00267    parameter b, allParam is assigned to contain a, b, c). */
00268   void ICCLogistic<1>::GetAllParameters(const RealVector &estParam, RealVector
00269       &allParam) const
00270   {
00271     if (estParam.size() != 1 || allParam.size() != 3)
00272     {
00273       throw
00274       InvalidArgument("Invalid number of parameters",
00275           "ICCLogistic<1>::GetAllParameters");
00276     }
00277     allParam[0] = fixedA;
00278     allParam[1] = estParam[0];
00279     allParam[2] = fixedC;
00280   }
00281 
00282 } // namespace etirm

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