00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #ifdef ETIRM_NO_DIR_PREFIX
00071 #include "swig_etirm.h"
00072 #include "MStepIRT.h"
00073 #include "DiscreteNormalDist.h"
00074 #include "ItemParamPriorBeta4.h"
00075 #include "ItemParamPriorLogNormal.h"
00076 #include "ItemParamPriorNormal.h"
00077 #include "BootstrapSample.h"
00078 #include "SimulateResponses.h"
00079 #include "ExamineeThetaMLE.h"
00080 #else
00081 #include "etirm/swig_etirm.h"
00082 #include "etirm/MStepIRT.h"
00083 #include "etirm/DiscreteNormalDist.h"
00084 #include "etirm/ItemParamPriorBeta4.h"
00085 #include "etirm/ItemParamPriorLogNormal.h"
00086 #include "etirm/ItemParamPriorNormal.h"
00087 #include "etirm/BootstrapSample.h"
00088 #include "etirm/SimulateResponses.h"
00089 #include "etirm/ExamineeThetaMLE.h"
00090 #endif
00091
00092
00093
00094 #include <boost/random/uniform_int.hpp>
00095
00096 #include <cstdio>
00097
00098 #ifdef BOOST_NO_STDC_NAMESPACE
00099 namespace std
00100 { using ::sprintf;}
00101 #endif
00102
00103
00104 namespace etirm
00105 {
00106
00107
00108 SwigEtirmRun *gEtirmRun = 0;
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 void ItemRespCounts::AddResponse(int respIndex, Real count, int group)
00122 {
00123
00124 if (respIndex > catCounts.size() || respIndex < 1)
00125 {
00126 throw InvalidArgument("Invalid response index", "ItemRespCounts::AddResponse");
00127 }
00128
00129 totalCount[0] += count;
00130 totalCount[group] += count;
00131
00132 catCounts(1, respIndex) += count;
00133 catCounts(group+1, respIndex) += count;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 SwigEtirmRun::SwigEtirmRun(int nitems, int nlatentcat, int ngroups, Real minTheta, Real maxTheta,
00153 bool uniquePoints) :
00154 numItems(nitems), numLatentCat(nlatentcat), numGroups(ngroups), examineeCounts(ngroups+1, 0.0),
00155 items(nitems), itemStats(nitems), minProc(nitems), latentDist(nlatentcat, ngroups,
00156 uniquePoints), rand_boot(0), base_rand_simulate(0), rand_simulate(0)
00157 {
00158 int i;
00159
00160
00161
00162 DiscreteNormalDist(nlatentcat, minTheta, maxTheta, latentDist.begin_points(1),
00163 latentDist.begin_weights(1));
00164
00165
00166 for (i=2; i<=ngroups; ++i)
00167 {
00168 DiscreteLatentDist<Real>::weight_iterator w1 = latentDist.begin_weights(1);
00169 DiscreteLatentDist<Real>::weight_iterator w2 = latentDist.begin_weights(i);
00170 for (int j = nlatentcat; j--; ++w1, ++w2)
00171 {
00172 *w2 = *w1;
00173 }
00174
00175 if (uniquePoints)
00176 {
00177
00178 DiscreteLatentDist<Real>::point_iterator w1p = latentDist.begin_points(1);
00179 DiscreteLatentDist<Real>::point_iterator w2p = latentDist.begin_points(i);
00180 for (int j = nlatentcat; j--; ++w1p, ++w2p)
00181 {
00182 *w2p = *w1p;
00183 }
00184 }
00185 }
00186
00187
00188 for (i=0; i<nitems; ++i)
00189 {
00190 items[i] = 0;
00191 itemStats[i] = 0;
00192 minProc[i] = 0;
00193 }
00194
00195 }
00196
00197
00198 SwigEtirmRun::~SwigEtirmRun()
00199 {
00200 int i;
00201
00202 for (i=0; i<numItems; i++)
00203 {
00204 if (items[i])
00205 {
00206 items[i]->DeletePriors();
00207 delete items[i];
00208 }
00209
00210 if (itemStats[i])
00211 delete itemStats[i];
00212 if (minProc[i])
00213 delete minProc[i];
00214 }
00215
00216 int n = examinees.size();
00217 for (i=0; i<n; ++i)
00218 {
00219 delete examinees[i];
00220 }
00221
00222 delete rand_boot;
00223 delete base_rand_simulate;
00224 delete rand_simulate;
00225 }
00226
00227
00228 void SwigEtirmRun::CheckExaminees(const char *funcname)
00229 {
00230 if ((gEtirmRun->examinees).size() == 0)
00231 {
00232 throw RuntimeError("Error: No examinee data", funcname);
00233 }
00234 }
00235
00236
00237 void SwigEtirmRun::CheckExamineeNumber(int examno, const char *funcname)
00238 {
00239 if ( (examno < 1) || ( examno > (gEtirmRun->examinees).size() ) )
00240 {
00241 char errstr[50];
00242 std::sprintf(errstr, "Invalid examinee number: %d", examno);
00243 gEtirmRun->returnString = errstr;
00244 throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00245 }
00246 }
00247
00248
00249 void SwigEtirmRun::CheckItemNumber(int itemno, const char *funcname)
00250 {
00251 if (itemno < 1 || itemno >(gEtirmRun->numItems) )
00252 {
00253 char errstr[50];
00254 std::sprintf(errstr, "Invalid item number: %d", itemno);
00255 gEtirmRun->returnString = errstr;
00256 throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00257 }
00258 }
00259
00260
00261
00262
00263 void SwigEtirmRun::CheckGroup(int group, const char *funcname)
00264 {
00265 if (group < 1 || group >(gEtirmRun->numGroups) )
00266 {
00267 char errstr[50];
00268 std::sprintf(errstr, "Invalid examinee group: %d", group);
00269 gEtirmRun->returnString = errstr;
00270 throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00271 }
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 void CheckItemParam(item_type *item, int index, const char *funcname)
00285 {
00286 if (item->NumParameters() <= index || index < 0)
00287 {
00288 char errstr[100];
00289 std::sprintf(errstr, "Invalid item parameter index for item %d: %d", item->Index()+1, index);
00290 gEtirmRun->returnString = errstr;
00291 throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00292 }
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 ItemParamPrior *CreatePrior(const std::string &pstr, const double_vector &priorparam,
00306 const char *funcname)
00307 {
00308 const char *err_message = "Invalid number of prior parameters";
00309
00310 if (pstr.compare("none") == 0)
00311 {
00312 return 0;
00313 }
00314 else if (pstr.compare("normal") == 0)
00315 {
00316 if (priorparam.size() != 2)
00317 throw RuntimeError(err_message, funcname);
00318 return new ItemParamPriorNormal(priorparam[0], priorparam[1]);
00319 }
00320 else if (pstr.compare("lognormal") == 0)
00321 {
00322 if (priorparam.size() != 2)
00323 throw RuntimeError(err_message, funcname);
00324 return new ItemParamPriorLogNormal(priorparam[0], priorparam[1]);
00325 }
00326 else if (pstr.compare("beta") == 0)
00327 {
00328 if (priorparam.size() != 4)
00329 throw RuntimeError(err_message, funcname);
00330 return new ItemParamPriorBeta4(priorparam[0], priorparam[1], priorparam[2], priorparam[3]);
00331 }
00332 else
00333 {
00334 throw RuntimeError("Invalid prior type", funcname);
00335 }
00336 return 0;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 char Resp2Char(Response r, const item_type *item)
00355 {
00356 const char zero = '0';
00357 Response np = item_type::NotPresentedResponse();
00358 char cr;
00359 if (r == np)
00360 cr = np - item->FirstResponse() + zero;
00361 else
00362 cr = item->ResponseIndex(r) + zero;
00363
00364 return cr;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 estep::estep(int_vector *itemno)
00381 {
00382 CheckRunInit();
00383
00384 if (itemno)
00385 {
00386 mItems = new ItemVector(ItemSubset(itemno,gEtirmRun->items,"new_estep"));
00387
00388 mEStep = new estep_type(mItems->begin(), mItems->end(), gEtirmRun->latentDist);
00389 }
00390 else
00391 {
00392 mItems = 0;
00393 mEStep = new estep_type((gEtirmRun->items).begin(), (gEtirmRun->items).end(), gEtirmRun->latentDist);
00394 }
00395 }
00396
00397
00398
00399
00400
00401 estep::~estep()
00402 {
00403 if (mItems)
00404 delete mItems;
00405 delete mEStep;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 double estep::compute(bool compute_post, bool store_post, int_vector *estep_items)
00434 {
00435 const char *fname = "estep_compute";
00436 CheckRunInit();
00437 gEtirmRun->CheckExaminees(fname);
00438
00439 if (estep_items)
00440 {
00441 if (estep_items->size() > 0)
00442 {
00443 ItemVector itemsub = ItemSubset(estep_items, gEtirmRun->items, fname);
00444 return mEStep->DoEStep((gEtirmRun->examinees).begin(), (gEtirmRun->examinees).end(), itemsub.begin(), itemsub.end(), compute_post, store_post);
00445 }
00446 else
00447 {
00448 return mEStep->DoEStep((gEtirmRun->examinees).begin(), (gEtirmRun->examinees).end(), (gEtirmRun->items).begin(), (gEtirmRun->items).begin(), compute_post, store_post);
00449 }
00450 }
00451 else
00452 {
00453 return mEStep->DoEStep((gEtirmRun->examinees).begin(), (gEtirmRun->examinees).end(), compute_post, store_post);
00454 }
00455 }
00456
00457
00458
00459
00460
00461 void set_missing_resp(char nr)
00462 {
00463 if (gEtirmRun)
00464 {
00465 throw RuntimeError("The not presented response can only be set before any items are initialized", 0);
00466 }
00467 Item<Real>::SetNotPresentedResponse(nr);
00468 }
00469
00470
00471
00472
00473
00474 int num_items()
00475 {
00476 CheckRunInit();
00477
00478 return gEtirmRun->numItems;
00479 }
00480
00481
00482
00483
00484
00485 int num_latent_dist_points()
00486 {
00487 CheckRunInit();
00488
00489 return gEtirmRun->numLatentCat;
00490 }
00491
00492
00493
00494
00495
00496 int num_groups()
00497 {
00498 CheckRunInit();
00499
00500 return gEtirmRun->numGroups;
00501 }
00502
00503
00504
00505
00506
00507 int num_examinees()
00508 {
00509 CheckRunInit();
00510
00511 return (gEtirmRun->examinees).size();
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 const char * item_get_model(int itemno)
00523 {
00524
00525 CheckRunInit();
00526 std::string &modelName = gEtirmRun->returnString;
00527 gEtirmRun->CheckItemNumber(itemno, "item_get_model");
00528
00529 item_type *item = (gEtirmRun->items)[itemno-1];
00530 modelName = item->ModelName();
00531
00532 return modelName.c_str();
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 void item_set_param(int paramno, int itemno, double paramvalue)
00546 {
00547 const char *fname = "item_set_param";
00548 CheckRunInit();
00549 int index = paramno - 1;
00550
00551 gEtirmRun->CheckItemNumber(itemno, fname);
00552 item_type *item = (gEtirmRun->items)[itemno-1];
00553 CheckItemParam(item, index, fname);
00554
00555
00556 item_type::prior_iterator pri = item->PriorsIterator() + index;
00557 if (*pri && (*pri)->ZeroDensity(paramvalue))
00558 {
00559 char merr[100];
00560 std::sprintf(merr, "Parameter specified for item %d has zero prior density", itemno);
00561 gEtirmRun->returnString = merr;
00562 throw RuntimeError((gEtirmRun->returnString).c_str(), fname);
00563 }
00564
00565 item_type::param_iterator pv = item->ParametersIterator();
00566
00567 pv[index] = paramvalue;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 void item_set_params(int itemno, double_vector *params)
00585 {
00586 const char *fname = "item_set_params";
00587 CheckRunInit();
00588 gEtirmRun->CheckItemNumber(itemno, fname);
00589
00590 item_type *item = (gEtirmRun->items)[itemno-1];
00591
00592
00593 item_type::param_iterator pv = item->ParametersIterator();
00594 double_vector::iterator iv = params->begin();
00595 int n;
00596 for (n = item->NumParameters(); n--; ++pv, ++iv)
00597 {
00598 *pv = *iv;
00599 }
00600
00601
00602 iv = params->begin();
00603 item_type::prior_iterator pri = item->PriorsIterator();
00604 for (n = item->NumParameters(); n--; ++pri, ++iv)
00605 {
00606 if (*pri && (*pri)->ZeroDensity(*iv))
00607 {
00608 char merr[100];
00609 std::sprintf(merr, "Parameter specified for item %d has zero prior density", itemno);
00610 throw InvalidArgument(merr, fname);
00611 }
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 void item_set_all_params(int itemno, double_vector *params)
00630 {
00631 const char *fname = "item_set_all_params";
00632 CheckRunInit();
00633 gEtirmRun->CheckItemNumber(itemno, fname);
00634
00635 item_type *item = (gEtirmRun->items)[itemno-1];
00636
00637
00638 item->SetAllParameters(*params);
00639
00640
00641 item_type::param_iterator iv = item->ParametersIterator();
00642 item_type::prior_iterator pri = item->PriorsIterator();
00643 for (int n = item->NumParameters(); n--; ++pri, ++iv)
00644 {
00645 if (*pri && (*pri)->ZeroDensity(*iv))
00646 {
00647 char merr[100];
00648 std::sprintf(merr, "Parameter specified for item %d has zero prior density", itemno);
00649 gEtirmRun->returnString = merr;
00650 throw InvalidArgument((gEtirmRun->returnString).c_str(), fname);
00651 }
00652 }
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 double item_get_param(int paramno, int itemno)
00669 {
00670 const char *fname = "item_get_param";
00671 CheckRunInit();
00672 int index = paramno - 1;
00673
00674 gEtirmRun->CheckItemNumber(itemno, fname);
00675 item_type *item = (gEtirmRun->items)[itemno-1];
00676 CheckItemParam(item, index, fname);
00677
00678 item_type::param_iterator pv = item->ParametersIterator();
00679
00680 return pv[index];
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 double_vector *item_get_params(int itemno)
00696 {
00697 CheckRunInit();
00698 gEtirmRun->CheckItemNumber(itemno, "item_get_params");
00699
00700 item_type *item = (gEtirmRun->items)[itemno-1];
00701
00702 int n = item->NumParameters();
00703 double_vector *params = new double_vector(n);
00704
00705 item_type::param_iterator pv = item->ParametersIterator();
00706 double_vector::iterator iv = params->begin();
00707 for (; n--; ++pv, ++iv)
00708 {
00709 *iv = *pv;
00710 }
00711
00712 return params;
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 double_vector *item_get_all_params(int itemno)
00728 {
00729 CheckRunInit();
00730 gEtirmRun->CheckItemNumber(itemno, "item_get_all_params");
00731
00732 item_type *item = (gEtirmRun->items)[itemno-1];
00733
00734 RealVector allparam = item->GetAllParameters();
00735 int n = allparam.size();
00736 double_vector *params = new double_vector(n);
00737
00738 RealVector::iterator pv = allparam.begin();
00739 double_vector::iterator iv = params->begin();
00740 for (; n--; ++pv, ++iv)
00741 {
00742 *iv = *pv;
00743 }
00744
00745 return params;
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 int item_num_params(int itemno)
00757 {
00758 CheckRunInit();
00759 gEtirmRun->CheckItemNumber(itemno, "item_num_params");
00760
00761 item_type *item = (gEtirmRun->items)[itemno-1];
00762
00763 return item->NumParameters();
00764 }
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 int item_num_resp_cat(int itemno)
00775 {
00776 CheckRunInit();
00777 gEtirmRun->CheckItemNumber(itemno, "item_num_resp_cat");
00778
00779 item_type *item = (gEtirmRun->items)[itemno-1];
00780
00781 return item->NumRespCat();
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 void item_set_prior(int paramno, int itemno, char *priortype, double_vector *dlist)
00796 {
00797 const char *funcname = "item_set_prior";
00798 CheckRunInit();
00799 int index = paramno - 1;
00800
00801 gEtirmRun->CheckItemNumber(itemno, funcname);
00802 item_type *item = (gEtirmRun->items)[itemno-1];
00803 CheckItemParam(item, index, funcname);
00804
00805 item_type::prior_iterator pv = item->PriorsIterator() + index;
00806
00807 if (*pv)
00808 delete *pv;
00809
00810 std::string pstr(priortype);
00811 *pv = CreatePrior(pstr, *dlist, funcname);
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 const char *item_get_prior_type(int paramno, int itemno)
00825 {
00826 const char *fname = "item_get_prior_type";
00827 CheckRunInit();
00828 std::string &priorName = gEtirmRun->returnString;
00829 int index = paramno - 1;
00830
00831 gEtirmRun->CheckItemNumber(itemno, fname);
00832 item_type *item = (gEtirmRun->items)[itemno-1];
00833 CheckItemParam(item, index, fname);
00834
00835 item_type::prior_iterator pv = item->PriorsIterator() + index;
00836
00837 if (*pv != 0)
00838 {
00839 priorName = (*pv)->DistributionName();
00840 }
00841 else
00842 {
00843 priorName = "none";
00844 }
00845
00846 return priorName.c_str();
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858 double_vector *item_get_prior_param(int paramno, int itemno)
00859 {
00860 const char *fname = "item_get_prior_param";
00861 CheckRunInit();
00862 int index = paramno - 1;
00863
00864 gEtirmRun->CheckItemNumber(itemno, fname);
00865 item_type *item = (gEtirmRun->items)[itemno-1];
00866 CheckItemParam(item, index, fname);
00867
00868 item_type::prior_iterator pv = item->PriorsIterator() + index;
00869
00870 double_vector *v;
00871 if (*pv != 0)
00872 {
00873 int n = (*pv)->NumParameters();
00874
00875 v = new double_vector(n);
00876
00877 *v = (*pv)->GetParameters();
00878 }
00879 else
00880 {
00881 v = new double_vector();
00882 }
00883
00884 return v;
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 double_vector *item_cat_counts(int itemno, int group)
00898 {
00899 const char *fname = "item_cat_counts";
00900 CheckRunInit();
00901
00902 gEtirmRun->CheckItemNumber(itemno, fname);
00903 if (group != 0)
00904 gEtirmRun->CheckGroup(group, "item_resp_count");
00905
00906 ItemRespCounts *stats = (gEtirmRun->itemStats)[itemno-1];
00907
00908 double_vector *v = new double_vector(stats->CategoryCounts(group));
00909
00910 return v;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 double item_resp_count(int itemno, int group)
00924 {
00925 CheckRunInit();
00926
00927 gEtirmRun->CheckItemNumber(itemno, "item_resp_count");
00928 if (group != 0)
00929 gEtirmRun->CheckGroup(group, "item_resp_count");
00930
00931 return (gEtirmRun->itemStats)[itemno-1]->RespCount(group);
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 int item_scale_params(int itemno, double slope, double intercept, bool ignorePriorE