00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ETIRM_ITEMDICHOTOMOUS_H_
00021 #define ETIRM_ITEMDICHOTOMOUS_H_
00022
00023 #ifdef ETIRM_NO_DIR_PREFIX
00024 #include "etirmtypes.h"
00025 #include "ItemNR.h"
00026 #else
00027 #include "etirm/etirmtypes.h"
00028 #include "etirm/ItemNR.h"
00029 #endif
00030
00031 #include <cmath>
00032 #if defined(ETIRM_USE_BOOST_CONFIG) || defined(BOOST_NO_LIMITS)
00033
00034
00035 #include <boost/detail/limits.hpp>
00036 #else
00037 #include <limits>
00038 #endif
00039
00040
00041 #ifdef BOOST_NO_STDC_NAMESPACE
00042 namespace std
00043 { using ::log;}
00044 #endif
00045
00046 namespace etirm
00047 {
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 template<class D, class ICC> class ItemDichotomous : public ItemNR<D>
00061 {
00062
00063 public:
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 ItemDichotomous(int index, ICC &icc, D *dist);
00082
00083
00084
00085
00086
00087 virtual ~ItemDichotomous();
00088
00089
00090
00091
00092
00093
00094
00095
00096 virtual RealVector GetAllParameters() const
00097 {
00098 RealVector allParam(mICC.NumAllParameters());
00099 mICC.GetAllParameters(ItemNR<D>::mParameterEstimates, allParam);
00100 return allParam;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 virtual void SetAllParameters(const RealVector &allParam)
00112 {
00113 mICC.SetAllParameters(allParam.begin(), allParam.end(), ItemNR<D>::mParameterEstimates);
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 virtual Real ICRF(Response r, const RealVector ¶meters, const Real &theta) const;
00127
00128
00129 virtual Real NormalizingConstant() const
00130 {
00131 return mICC.GetD();
00132 }
00133
00134 virtual int ScaleParameters(Real slope, Real intercept, bool ignorePrior = false);
00135
00136
00137 virtual std::string ModelName() const
00138 {
00139 return mICC.Name();
00140 }
00141
00142
00143 virtual IRTModel Model() const
00144 {
00145 return mICC.Model();
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 virtual void SetFirstResponse(Response r)
00157 {
00158 ItemNR<D>::mFirstResponse = r;
00159 mCorrectResponse = r+1;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169 virtual Response CorrectResponse()
00170 {
00171 return mCorrectResponse;
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181 Response IncorrectResponse()
00182 {
00183 return mCorrectResponse-1;
00184 }
00185
00186
00187
00188
00189 virtual double f_to_minimize(RealVector &p);
00190
00191 virtual void gradient(RealVector &p, RealVector &g);
00192
00193 virtual void hessian(RealVector &x, RealMatrix &h);
00194
00195 virtual int HasAnalyticGradient() const;
00196
00197 virtual int HasAnalyticHessian() const;
00198
00199 virtual int ValidParameters(const RealVector &p, bool ignorePriors = false) const;
00200
00201 protected:
00202
00203 ICC mICC;
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 Response mCorrectResponse;
00214
00215 };
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 template<class D, class ICC> ItemDichotomous<D, ICC>::ItemDichotomous(int index, ICC &icc,
00239 D *dist) :
00240 ItemNR<D>(icc.NumParameters(), index, 2, dist), mICC(icc),
00241 mCorrectResponse(ItemNR<D>::mFirstResponse+1)
00242 {
00243
00244 }
00245
00246 template<class D, class ICC> ItemDichotomous<D, ICC>::~ItemDichotomous()
00247 {
00248 }
00249
00250 template<class D, class ICC> inline Real ItemDichotomous<D, ICC>::ICRF(Response r,
00251 const RealVector ¶meters, const Real &theta) const
00252 {
00253 return (r == mCorrectResponse) ? mICC.ICC(parameters, theta) : (1.0 - mICC.ICC(parameters,
00254 theta));
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 template<class D, class ICC> double ItemDichotomous<D, ICC>::f_to_minimize(RealVector ¶m)
00275 {
00276 Real value = 0.0;
00277 int ngroups = ItemNR<D>::mLatentDist->NumGroupsUnique();
00278
00279
00280 for (int grp=1; grp<=ngroups; ++grp)
00281 {
00282 typename ItemNR<D>::n_iterator in = ItemNR<D>::NVector(grp);
00283 typename ItemNR<D>::r_iterator ir = ItemNR<D>::RVector(mCorrectResponse, grp);
00284 typename ItemNR<D>::point_iterator it = ItemNR<D>::mLatentDist->begin_points(grp);
00285 for (int i = ItemNR<D>::mNumLatentVarCat; i--; ++in, ++ir, ++it)
00286 {
00287 Real prob = mICC.OpenICC(param, *it);
00288
00289 Real t = std::log(prob) * *ir;
00290 t += (*in - *ir) * std::log((1.0 - prob));
00291 value += t;
00292 }
00293 }
00294
00295
00296 PriorVector::const_iterator iprior = ItemNR<D>::mPriors.begin();
00297 RealVector::iterator iparam = param.begin();
00298 for (int j = ItemNR<D>::NumParameters(); j--; ++iprior, ++iparam)
00299 {
00300 if (*iprior)
00301 {
00302 if ((*iprior)->ZeroDensity(*iparam))
00303 {
00304
00305
00306
00307 if (std::numeric_limits<Real>::has_infinity)
00308 {
00309 return std::numeric_limits<Real>::infinity();
00310 }
00311 else
00312 {
00313 return std::numeric_limits<Real>::max();
00314 }
00315 }
00316 else
00317 {
00318 value += (*iprior)->LogDensity(*iparam);
00319 }
00320 }
00321 }
00322
00323 return -value;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 template<class D, class ICC> void ItemDichotomous<D, ICC>::gradient(RealVector ¶m,
00345 RealVector &g)
00346 {
00347 g = 0.0;
00348 RealVector deriv(ItemNR<D>::NumParameters());
00349 int ngroups = ItemNR<D>::mLatentDist->NumGroupsUnique();
00350
00351 int i;
00352
00353 for (int grp=1; grp<=ngroups; ++grp)
00354 {
00355 typename ItemNR<D>::n_iterator in = ItemNR<D>::NVector(grp);
00356 typename ItemNR<D>::r_iterator ir = ItemNR<D>::RVector(mCorrectResponse, grp);
00357 typename ItemNR<D>::point_iterator itheta = ItemNR<D>::mLatentDist->begin_points(grp);
00358 for (i = ItemNR<D>::mNumLatentVarCat; i--; ++in, ++ir, ++itheta)
00359 {
00360 Real prob = mICC.OpenICC(param, *itheta);
00361
00362 Real t = *ir - *in * prob;
00363 t /= (1.0 - prob) * prob;
00364
00365 mICC.ICCDeriv1(param, *itheta, deriv);
00366
00367
00368 deriv *= -t;
00369 g += deriv;
00370
00371 }
00372 }
00373
00374
00375 PriorVector::const_iterator iprior = ItemNR<D>::mPriors.begin();
00376 RealVector::iterator iparam = param.begin();
00377 RealVector::iterator ig = g.begin();
00378 for (int j = ItemNR<D>::NumParameters(); j--; ++iprior, ++iparam, ++ig)
00379 {
00380
00381 if (*iprior)
00382 *ig -= (*iprior)->DerivLogDensity1(*iparam);
00383 }
00384
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 template<class D, class ICC> void ItemDichotomous<D, ICC>::hessian(RealVector ¶m,
00408 RealMatrix &h)
00409 {
00410 int numParameters = ItemNR<D>::NumParameters();
00411
00412 RealMatrix deriv2(numParameters, numParameters);
00413 RealVector deriv1(numParameters);
00414
00415 RealMatrix::diag_iterator hdiag, ddiag;
00416 int i, j, k;
00417 int ngroups = ItemNR<D>::mLatentDist->NumGroupsUnique();
00418
00419
00420 for (i=0; i<numParameters; ++i)
00421 {
00422 hdiag = h.begin_diagonal(i+1, 1);
00423 for (j=numParameters-i; j--; ++hdiag)
00424 {
00425 *hdiag = 0.0;
00426 }
00427 }
00428
00429 for (int grp=1; grp<=ngroups; ++grp)
00430 {
00431 typename ItemNR<D>::n_iterator in = ItemNR<D>::NVector(grp);
00432 typename ItemNR<D>::r_iterator ir = ItemNR<D>::RVector(mCorrectResponse, grp);
00433 typename ItemNR<D>::point_iterator itheta = ItemNR<D>::mLatentDist->begin_points(grp);
00434 for (k = ItemNR<D>::mNumLatentVarCat; k--; ++in, ++ir, ++itheta)
00435 {
00436 Real prob = mICC.OpenICC(param, *itheta);
00437 Real t1 = -*in * prob * prob;
00438 t1 += 2.0 * *ir * prob;
00439 t1 -= *ir;
00440 Real t2 = *ir - *in * prob;
00441 Real t = prob * (1.0 - prob);
00442 t1 /= t * t;
00443 t2 /= t;
00444
00445 mICC.ICCDeriv1(param, *itheta, deriv1);
00446 mICC.ICCDeriv2(param, *itheta, deriv2);
00447
00448 for (int i=0; i<numParameters; ++i)
00449 {
00450 hdiag = h.begin_diagonal(i+1, 1);
00451 ddiag = deriv2.begin_diagonal(i+1, 1);
00452 RealVector::iterator prow = deriv1.begin() + i;
00453 RealVector::iterator pcol = deriv1.begin();
00454 for (j=numParameters-i; j--; ++prow, ++pcol, ++hdiag, ++ddiag)
00455 {
00456
00457 *hdiag -= t1 * *prow * *pcol;
00458 *hdiag -= t2 * *ddiag;
00459 }
00460 }
00461 }
00462 }
00463
00464
00465 PriorVector::const_iterator iprior = ItemNR<D>::mPriors.begin();
00466 RealVector::iterator iparam = param.begin();
00467 hdiag = h.begin_diagonal(1, 1);
00468 for (i = numParameters; i--; ++iparam, ++iprior, ++hdiag)
00469 {
00470
00471 if (*iprior)
00472 *hdiag -= (*iprior)->DerivLogDensity2(*iparam);
00473 }
00474
00475 }
00476
00477
00478 template<class D, class ICC> int ItemDichotomous<D, ICC>::HasAnalyticGradient() const
00479 {
00480 return mICC.GradientDefined();
00481 }
00482
00483
00484 template<class D, class ICC> int ItemDichotomous<D, ICC>::HasAnalyticHessian() const
00485 {
00486 return mICC.HessianDefined();
00487 }
00488
00489
00490 template<class D, class ICC> int ItemDichotomous<D, ICC>::ValidParameters(
00491 const RealVector ¶m, bool ignorePriors) const
00492 {
00493 if (!(mICC.ValidParameters(param)))
00494 return 0;
00495
00496 return ItemNR<D>::ValidParameters(param, ignorePriors);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 template<class D, class ICC> int ItemDichotomous<D, ICC>::ScaleParameters(Real slope,
00515 Real intercept, bool ignorePriors)
00516 {
00517 RealVector scaledParam(ItemNR<D>::mParameterEstimates);
00518
00519 mICC.Scale(slope, intercept, scaledParam);
00520
00521
00522 if (!(ValidParameters(scaledParam, ignorePriors)))
00523 return 1;
00524
00525 ItemNR<D>::mParameterEstimates = scaledParam;
00526
00527 return 0;
00528 }
00529
00530 }
00531
00532 #endif //ETIRM_ITEMDICHOTOMOUS_H_