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 ignorePriorError)
00949 {
00950 CheckRunInit();
00951
00952 gEtirmRun->CheckItemNumber(itemno, "item_scale_params");
00953 item_type *item = (gEtirmRun->items)[itemno-1];
00954
00955 return item->ScaleParameters(slope, intercept, ignorePriorError);
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 double item_prob_resp(int itemno, int response, double theta)
00971 {
00972 CheckRunInit();
00973 gEtirmRun->CheckItemNumber(itemno, "item_prob_resp");
00974
00975 item_type *item = (gEtirmRun->items)[itemno-1];
00976
00977 return item->ProbResp(item->IndexResponse(response), theta);
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993 double_vector *test_characteristic_curve(double_vector *thetas, int_vector *ilist2)
00994 {
00995 CheckRunInit();
00996
00997 double_vector tcc(thetas->size(), 0.0);
00998
00999
01000 double_vector probs;
01001
01002 ItemVector *sitems;
01003 if (ilist2)
01004 {
01005 sitems = new ItemVector(ItemSubset(ilist2, gEtirmRun->items, "test_characteristic_curve"));
01006 }
01007 else
01008 {
01009 sitems = &(gEtirmRun->items);
01010 }
01011
01012
01013 ItemVector::iterator ii = sitems->begin();
01014 for (int i = sitems->size(); i--; ++ii)
01015 {
01016 int ncat = (*ii)->NumRespCat();
01017 probs.newsize(ncat);
01018
01019 double_vector::iterator icc = tcc.begin();
01020 double_vector::iterator it = thetas->begin();
01021 for (int j = tcc.size(); j--; ++icc, ++it)
01022 {
01023 (*ii)->ProbRespAll(*it, probs.begin());
01024
01025
01026
01027 double dresp = 1.0;
01028 double sum = 0.0;
01029 double_vector::iterator ip = probs.begin()+1;
01030 for (int k = ncat-1; k--; ++ip, ++dresp)
01031 {
01032 sum += dresp * *ip;
01033 }
01034
01035
01036 *icc += sum;
01037 }
01038 }
01039
01040 if (ilist2)
01041 delete sitems;
01042
01043 return new double_vector(tcc);
01044 }
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 void dist_set_points(double_vector *dlist, int group)
01056 {
01057 CheckRunInit();
01058 gEtirmRun->CheckGroup(group, "dist_set_points");
01059
01060 int n = dlist->size();
01061 if (n != (gEtirmRun->latentDist).size())
01062 {
01063 throw RuntimeError("Number of points does not match number of categories in latent distribution",
01064 "dist_set_points");
01065 }
01066
01067 DiscreteLatentDist<Real>::point_iterator ip = (gEtirmRun->latentDist).begin_points(group);
01068
01069 double_vector::iterator id = dlist->begin();
01070 for (; n--; ++ip, ++id)
01071 {
01072 *ip = *id;
01073 }
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 void dist_set_point(int index, double p, int group)
01087 {
01088 CheckRunInit();
01089 gEtirmRun->CheckGroup(group, "dist_set_point");
01090
01091 if (index < 1 || index> (gEtirmRun->latentDist).size())
01092 {
01093 throw RuntimeError("Invalid category of latent variable distribution","dist_set_point");
01094 }
01095
01096 DiscreteLatentDist<Real>::point_iterator ip = (gEtirmRun->latentDist).begin_points(group);
01097
01098 ip[index-1] = p;
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 double_vector *dist_get_points(int group)
01110 {
01111 CheckRunInit();
01112 gEtirmRun->CheckGroup(group, "dist_get_points");
01113
01114 DiscreteLatentDist<Real>::point_iterator ip = (gEtirmRun->latentDist).begin_points(group);
01115
01116 int n = (gEtirmRun->latentDist).size();
01117 double_vector *outv = new double_vector(n);
01118 double_vector::iterator id = outv->begin();
01119 for (; n--; ++ip, ++id)
01120 {
01121 *id = *ip;
01122 }
01123
01124 return outv;
01125 }
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 double dist_get_point(int index, int group)
01137 {
01138 CheckRunInit();
01139 gEtirmRun->CheckGroup(group, "dist_get_point");
01140
01141 if (index < 1 || index> (gEtirmRun->latentDist).size())
01142 {
01143 throw RuntimeError("Invalid category of latent variable distribution","dist_get_point");
01144 }
01145
01146 DiscreteLatentDist<Real>::point_iterator ip = (gEtirmRun->latentDist).begin_points(group);
01147
01148 return ip[index-1];
01149 }
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160 void dist_set_probs(double_vector *dlist, int group)
01161 {
01162 CheckRunInit();
01163 gEtirmRun->CheckGroup(group, "dist_set_probs");
01164
01165 int n = dlist->size();
01166 if (n != (gEtirmRun->latentDist).size())
01167 {
01168 throw RuntimeError("Number of probabilities does not match number of categories in latent distribution",
01169 "dist_set_probs");
01170 }
01171
01172
01173 DiscreteLatentDist<Real>::weight_iterator ip = (gEtirmRun->latentDist).begin_weights(group);
01174 double_vector::iterator id = dlist->begin();
01175 Real sum = 0.0;
01176 for (; n--; ++ip, ++id)
01177 {
01178 *ip = *id;
01179 sum += *ip;
01180 }
01181
01182
01183 ip = (gEtirmRun->latentDist).begin_weights(group);
01184 for (n = dlist->size(); n--; ++ip)
01185 {
01186 *ip /= sum;
01187 }
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200 void dist_set_prob(int index, double w, int group)
01201 {
01202 CheckRunInit();
01203 gEtirmRun->CheckGroup(group, "dist_set_prob");
01204
01205 if (index < 1 || index> (gEtirmRun->latentDist).size())
01206 {
01207 throw RuntimeError("Invalid category of latent variable distribution","dist_set_prob");
01208 }
01209
01210 DiscreteLatentDist<Real>::weight_iterator ip = (gEtirmRun->latentDist).begin_weights(group);
01211
01212 ip[index-1] = w;
01213 }
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224 double_vector *dist_get_probs(int group)
01225 {
01226 CheckRunInit();
01227 gEtirmRun->CheckGroup(group, "dist_get_probs");
01228
01229 DiscreteLatentDist<Real>::weight_iterator ip = (gEtirmRun->latentDist).begin_weights(group);
01230
01231 int n = (gEtirmRun->latentDist).size();
01232 double_vector *outv = new double_vector(n);
01233 double_vector::iterator id = outv->begin();
01234 for (; n--; ++ip, ++id)
01235 {
01236 *id = *ip;
01237 }
01238
01239 return outv;
01240
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 double dist_get_prob(int index, int group)
01254 {
01255 CheckRunInit();
01256 gEtirmRun->CheckGroup(group, "dist_get_prob");
01257
01258 if (index < 1 || index> (gEtirmRun->latentDist).size())
01259 {
01260 throw RuntimeError("Invalid category of latent variable distribution","dist_get_prob");
01261 }
01262
01263 DiscreteLatentDist<Real>::weight_iterator ip = (gEtirmRun->latentDist).begin_weights(group);
01264
01265 return ip[index-1];
01266 }
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 void dist_transform(double slope, double intercept)
01278 {
01279 CheckRunInit();
01280
01281 (gEtirmRun->latentDist).Transform(slope, intercept);
01282 }
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295 double_vector *dist_scale(double mean, double sd, int group)
01296 {
01297 CheckRunInit();
01298 gEtirmRun->CheckGroup(group, "dist_scale");
01299
01300 double slope, intercept;
01301 (gEtirmRun->latentDist).Scale(mean, sd, group, slope, intercept);
01302
01303 double_vector *outv = new double_vector(2);
01304
01305 (*outv)[0] = slope;
01306 (*outv)[1] = intercept;
01307
01308 return outv;
01309 }
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320 double_vector *dist_mean_sd(int group)
01321 {
01322 CheckRunInit();
01323 gEtirmRun->CheckGroup(group, "dist_mean_sd");
01324
01325 double mean, sd;
01326 (gEtirmRun->latentDist).MeanSD(group, mean, sd);
01327
01328 double_vector *outv = new double_vector(2);
01329
01330 (*outv)[0] = mean;
01331 (*outv)[1] = sd;
01332
01333 return outv;
01334 }
01335
01336
01337
01338
01339
01340
01341 int dist_unique_points()
01342 {
01343 CheckRunInit();
01344
01345 return ((gEtirmRun->latentDist).NumGroupsUnique() > 1 && (gEtirmRun->latentDist).NumGroups() > 1);
01346 }
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364 double_vector *normal_dist_prob(int npoints, double minPoint, double maxPoint, double mean,
01365 double sd)
01366 {
01367 RealVector points(npoints);
01368 RealVector *prob = new RealVector(npoints);
01369
01370 DiscreteNormalDist(npoints, minPoint, maxPoint, points.begin(), prob->begin(), mean, sd);
01371
01372 return prob;
01373 }
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387 double_vector *normal_dist_points(int npoints, double minPoint, double maxPoint, double mean,
01388 double sd)
01389 {
01390 RealVector prob(npoints);
01391 RealVector *points = new RealVector(npoints);
01392
01393
01394 DiscreteNormalDist(npoints, minPoint, maxPoint, points->begin(), prob.begin(), mean, sd);
01395
01396 return points;
01397 }
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412 int mstep_items(bool ignore_max_iter, int_vector *itemno)
01413 {
01414 CheckRunInit();
01415
01416 if (itemno)
01417 {
01418 const char *fname = "mstep_items";
01419 ItemVector itemsub = ItemSubset(itemno, gEtirmRun->items, fname);
01420 UncminVector minsub = ItemSubset(itemno, gEtirmRun->minProc, fname);
01421 return MStepItems(minsub.begin(), itemsub.begin(), itemsub.end(), gEtirmRun->mstepMaxDiff,
01422 ignore_max_iter);
01423 }
01424 else
01425 {
01426 return MStepItems((gEtirmRun->minProc).begin(), (gEtirmRun->items).begin(), (gEtirmRun->items).end(), gEtirmRun->mstepMaxDiff, ignore_max_iter);
01427 }
01428 }
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 int mstep_message(int itemno)
01439 {
01440 CheckRunInit();
01441 gEtirmRun->CheckItemNumber(itemno, "mstep_message");
01442
01443 return ((gEtirmRun->minProc)[itemno-1])->GetMessage();
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456 void mstep_max_iter(int itemno, int maxiter)
01457 {
01458 CheckRunInit();
01459 gEtirmRun->CheckItemNumber(itemno, "mstep_max_iter");
01460
01461 return ((gEtirmRun->minProc)[itemno-1])->SetMaxIter(maxiter);
01462 }
01463
01464
01465
01466
01467
01468
01469 double mstep_max_diff()
01470 {
01471 CheckRunInit();
01472
01473 return gEtirmRun->mstepMaxDiff;
01474 }
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487 double mstep_dist(estep *e, int group)
01488 {
01489 CheckRunInit();
01490 gEtirmRun->CheckGroup(group, "mstep_dist");
01491
01492 estep_type::ngroup_iterator i = (e->GetEStep())->GetNGroup(group);
01493 RealVector::size_type n = (e->GetEStep())->size();
01494 RealVector prob(i, i+n);
01495 return (gEtirmRun->latentDist).MStep(prob, group);
01496 }
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514 int add_examinee(int_vector *responses, int group, double count)
01515 {
01516 const char *fname = "add_examinee";
01517 CheckRunInit();
01518 gEtirmRun->CheckGroup(group, fname);
01519
01520 int len = responses->size();
01521
01522 if (len != gEtirmRun->numItems)
01523 {
01524 throw RuntimeError("Invalid number of item responses", fname);
01525 }
01526
01527 examinee_type *e = new examinee_type(len, group);
01528
01529 ResponseVector r(len);
01530 ItemVector::iterator iitem = (gEtirmRun->items).begin();
01531 int_vector::iterator iir = responses->begin();
01532 ResponseVector::iterator ir = r.begin();
01533 ItemStatsVector::iterator is = (gEtirmRun->itemStats).begin();
01534 Response np = Item<Real>::NotPresentedResponse();
01535 for (; len--; ++iitem, ++iir, ++ir, ++is)
01536 {
01537 if (*iir < 0)
01538 *ir = np;
01539 else
01540 {
01541 *ir = (*iitem)->IndexResponse(*iir);
01542 if (!((*iitem)->ValidResponse(*ir)))
01543 {
01544 throw RuntimeError("Invalid item response", fname);
01545 }
01546 (*is)->AddResponse(*iir+1, count, group);
01547 }
01548 }
01549
01550 e->SetResponses(r);
01551 e->SetCount(count);
01552
01553 (gEtirmRun->examinees).push_back(e);
01554
01555 (gEtirmRun->examineeCounts)[0] += count;
01556 (gEtirmRun->examineeCounts)[group] += count;
01557
01558 return (gEtirmRun->examinees).size();
01559 }
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574 int_vector *examinee_responses(int examineeno)
01575 {
01576 const char *fname = "examinee_responses";
01577 CheckRunInit();
01578 gEtirmRun->CheckExamineeNumber(examineeno, fname);
01579
01580 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01581
01582 if ((gEtirmRun->items).size() != examinee->NumItems())
01583 {
01584 throw RuntimeError("Number of examinee responses does not match number of items", fname);
01585 }
01586
01587
01588 examinee_type::response_iterator first = examinee->responses_begin();
01589 examinee_type::response_iterator last = examinee->responses_end();
01590
01591 int_vector *responses = new int_vector(examinee->NumItems());
01592 int_vector::iterator ir = responses->begin();
01593 ItemVector::iterator ii = (gEtirmRun->items).begin();
01594 Response np = Item<Real>::NotPresentedResponse();
01595 while (first != last)
01596 {
01597 if (*first == np)
01598 *ir = -1;
01599 else
01600 *ir = (*ii)->ResponseIndex(*first);
01601 ++ir;
01602 ++ii;
01603 ++first;
01604 }
01605
01606 return responses;
01607 }
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 const char *examinee_response_str(int examineeno)
01625 {
01626 const char *fname = "examinee_response_str";
01627 CheckRunInit();
01628 gEtirmRun->CheckExamineeNumber(examineeno, fname);
01629
01630 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01631
01632 if ((gEtirmRun->items).size() != examinee->NumItems())
01633 {
01634 throw RuntimeError("Number of examinee responses does not match number of items", fname);
01635 }
01636
01637
01638 examinee_type::response_iterator first = examinee->responses_begin();
01639 examinee_type::response_iterator last = examinee->responses_end();
01640
01641 std::string &responseStr = gEtirmRun->returnString;
01642 responseStr.clear();
01643 ItemVector::iterator ii = (gEtirmRun->items).begin();
01644 while (first != last)
01645 {
01646 responseStr.push_back(Resp2Char(*first, *ii));
01647 ++ii;
01648 ++first;
01649 }
01650
01651 return responseStr.c_str();
01652 }
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663 int examinee_get_group(int examineeno)
01664 {
01665 CheckRunInit();
01666 gEtirmRun->CheckExamineeNumber(examineeno, "examinee_group");
01667
01668 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01669
01670 return examinee->Group();
01671 }
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682 void examinee_set_group(int examineeno, int group)
01683 {
01684 CheckRunInit();
01685 gEtirmRun->CheckExamineeNumber(examineeno, "examinee_set_group");
01686
01687 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01688
01689 return examinee->SetGroup(group);
01690 }
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 void examinee_set_count(int examineeno, double count)
01702 {
01703 CheckRunInit();
01704 gEtirmRun->CheckExamineeNumber(examineeno, "examinee_set_count");
01705
01706 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01707
01708 examinee->SetCount(count);
01709 }
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719 double examinee_get_count(int examineeno)
01720 {
01721 CheckRunInit();
01722 gEtirmRun->CheckExamineeNumber(examineeno, "examinee_get_count");
01723
01724 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01725
01726 return examinee->Count();
01727 }
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738 void examinee_set_posterior(int examineeno, double_vector *posterior)
01739 {
01740 CheckRunInit();
01741 gEtirmRun->CheckExamineeNumber(examineeno, "examinee_set_posterior");
01742
01743 if (posterior->size() != (gEtirmRun->latentDist).size())
01744 {
01745 throw RuntimeError("Invalid number of posterior probabilities",
01746 "examinee_set_posterior");
01747 }
01748
01749 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01750
01751 examinee_type::posterior_vector epost(gEtirmRun->numLatentCat);
01752 examinee_type::posterior_vector::iterator iep = epost.begin();
01753 double_vector::iterator ip = posterior->begin();
01754
01755
01756 int i;
01757 Real sum = 0.0;
01758 for (i = gEtirmRun->numLatentCat; i--; ++iep, ++ip)
01759 {
01760 *iep = *ip;
01761 sum += *iep;
01762 }
01763
01764
01765 iep = epost.begin();
01766 for (i = gEtirmRun->numLatentCat; i--; ++iep)
01767 {
01768 *iep /= sum;
01769 }
01770
01771 examinee->SetPosterior(epost);
01772 }
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782 double_vector* examinee_get_posterior(int examineeno)
01783 {
01784 char *fname = "examinee_get_posterior";
01785 CheckRunInit();
01786 gEtirmRun->CheckExamineeNumber(examineeno, fname);
01787
01788 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01789 int n = examinee->NumLatentVarCat();
01790
01791 if (n == 0)
01792 {
01793 char merr[100];
01794 std::sprintf(merr, "Posterior has not been computed for examinee %d", examineeno);
01795 gEtirmRun->returnString = merr;
01796 throw RuntimeError((gEtirmRun->returnString).c_str(), fname);
01797 }
01798
01799 double_vector *post = new double_vector(n);
01800
01801 examinee_type::posterior_vector::iterator ie = examinee->posterior_begin();
01802 double_vector::iterator ip = post->begin();
01803 for (; n--; ++ie, ++ip)
01804 {
01805 *ip = *ie;
01806 }
01807
01808 return post;
01809 }
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821 double examinee_posterior_mean(int examineeno)
01822 {
01823 char *fname = "examinee_posterior_mean";
01824 CheckRunInit();
01825 gEtirmRun->CheckExamineeNumber(examineeno, fname);
01826
01827 examinee_type *examinee = (gEtirmRun->examinees)[examineeno-1];
01828 int n = examinee->NumLatentVarCat();
01829
01830 if (n == 0)
01831 {
01832 char merr[100];
01833 std::sprintf(merr, "Posterior distribution has not been computed for examinee %d", examineeno);
01834 gEtirmRun->returnString = merr;
01835 throw RuntimeError((gEtirmRun->returnString).c_str(), fname);
01836 }
01837
01838 examinee_type::posterior_vector::iterator iw = examinee->posterior_begin();
01839 lvdist_type::point_iterator ip = (gEtirmRun->latentDist).begin_points();
01840 double mean = 0.0;
01841 for (; n--; ++iw, ++ip)
01842 {
01843 mean += *ip * *iw;
01844 }
01845
01846 return mean;
01847 }
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 double examinee_theta_MLE(int examineeno, double minTheta, double maxTheta, double precision,
01866 int_vector *itemno5)
01867 {
01868 CheckRunInit();
01869 gEtirmRun->CheckExamineeNumber(examineeno, "examinee_theta_MLE");
01870
01871 if (!gEtirmRun->base_rand_simulate)
01872 {
01873 gEtirmRun->base_rand_simulate = new random_type();
01874 gEtirmRun->rand_simulate = new boost::uniform_01<random_type>(*(gEtirmRun->base_rand_simulate));
01875 }
01876
01877 ItemVector *sitems;
01878 if (itemno5)
01879 {
01880 sitems = new ItemVector(ItemSubset(itemno5, gEtirmRun->items, "examinee_theta_MLE"));
01881 }
01882 else
01883 {
01884 sitems = &(gEtirmRun->items);
01885 }
01886
01887 double theta =
01888 ExamineeThetaMLE<ItemVector::iterator, examinee_type::response_vector::iterator>(minTheta,
01889 maxTheta, precision, sitems->begin(), sitems->end(), (gEtirmRun->examinees[examineeno-1])->responses_begin());
01890
01891 if (itemno5)
01892 delete sitems;
01893
01894 return theta;
01895 }
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906 double examinees_count(int group)
01907 {
01908 CheckRunInit();
01909 if (group != 0)
01910 gEtirmRun->CheckGroup(group, "examinee_count");
01911
01912 return (gEtirmRun->examineeCounts)[group];
01913 }
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923 void bootstrap_seed(unsigned long seed)
01924 {
01925 CheckRunInit();
01926
01927
01928 boost::uint32_t boost_seed = seed;
01929
01930 if (gEtirmRun->rand_boot)
01931 {
01932 gEtirmRun->rand_boot->seed(boost_seed);
01933 }
01934 else
01935 {
01936 gEtirmRun->rand_boot = new random_type(boost_seed);
01937 }
01938 }
01939
01940
01941
01942
01943
01944 void bootstrap_sample()
01945 {
01946 CheckRunInit();
01947 gEtirmRun->CheckExaminees("bootstrap_sample");
01948
01949 if (!gEtirmRun->rand_boot)
01950 gEtirmRun->rand_boot = new random_type();
01951
01952 boost::uniform_int<random_type> urand(*(gEtirmRun->rand_boot), 1, (gEtirmRun->examinees).size());
01953
01954 BootstrapSample((gEtirmRun->examinees).begin(), (gEtirmRun->examinees).end(), urand);
01955
01956
01957 gEtirmRun->examineeCounts = 0.0;
01958 ExamineeVector::iterator ie = (gEtirmRun->examinees).begin();
01959 for (int i = (gEtirmRun->examinees).size(); i--; ++ie)
01960 {
01961 double count = (*ie)->Count();
01962 (gEtirmRun->examineeCounts)[0] += count;
01963 int group = (*ie)->Group();
01964 (gEtirmRun->examineeCounts)[group] += count;
01965 }
01966 }
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976 void simulate_seed(unsigned long seed)
01977 {
01978 CheckRunInit();
01979
01980
01981 boost::uint32_t boost_seed = seed;
01982
01983 if (gEtirmRun->base_rand_simulate)
01984 {
01985 gEtirmRun->base_rand_simulate->seed(boost_seed);
01986 }
01987 else
01988 {
01989 gEtirmRun->base_rand_simulate = new random_type(boost_seed);
01990 gEtirmRun->rand_simulate = new boost::uniform_01<random_type>(*(gEtirmRun->base_rand_simulate));
01991 }
01992 }
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008 int_vector *simulate_responses(double theta, int_vector *itemno2)
02009 {
02010 CheckRunInit();
02011
02012 if (!gEtirmRun->base_rand_simulate)
02013 {
02014 gEtirmRun->base_rand_simulate = new random_type();
02015 gEtirmRun->rand_simulate = new boost::uniform_01<random_type>(*(gEtirmRun->base_rand_simulate));
02016 }
02017
02018 int_vector *resp;
02019 if (itemno2)
02020 {
02021 resp = new int_vector(itemno2->size());
02022 ItemVector sitems = ItemSubset(itemno2, gEtirmRun->items, "simulate_responses");
02023 resp->newsize(sitems.size());
02024 SimulateResponses(sitems.begin(), sitems.end(), theta, *(gEtirmRun->rand_simulate),
02025 resp->begin(), true);
02026 }
02027 else
02028 {
02029 resp = new int_vector((gEtirmRun->items).size());
02030 SimulateResponses((gEtirmRun->items).begin(), (gEtirmRun->items).end(), theta, *(gEtirmRun->rand_simulate), resp->begin(), true);
02031 }
02032
02033 return resp;
02034 }
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055 const char *simulate_response_str(double theta, int_vector *itemno2)
02056 {
02057 CheckRunInit();
02058
02059
02060 int_vector *iresp = simulate_responses(theta, itemno2);
02061
02062
02063 std::string &responseStr = gEtirmRun->returnString;
02064 responseStr.resize(iresp->size());
02065
02066
02067 int_vector::iterator ii = iresp->begin();
02068 std::string::iterator ic = responseStr.begin();
02069 for (int i = iresp->size(); i--; ++ii, ++ic)
02070 {
02071 if (*ii < 0)
02072 {
02073 *ic = item_type::NotPresentedResponse();
02074 }
02075 else
02076 {
02077 *ic = *ii + '0';
02078 }
02079 }
02080
02081 delete iresp;
02082
02083 return responseStr.c_str();
02084 }
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102 int_vector *get_responses(char *line, int_vector *offset, int_vector *len)
02103 {
02104 const char *fname = "get_responses";
02105 CheckRunInit();
02106
02107 int n = offset->size();
02108
02109 if (n != len->size())
02110 {
02111 throw InvalidArgument("Lengths of offset and length vectors do not match", fname);
02112 }
02113
02114 int_vector *resp = new int_vector(n);
02115
02116 int_vector::iterator ir = resp->begin();
02117 int_vector::iterator ioff = offset->begin();
02118 int_vector::iterator ilen = len->begin();
02119 Response np = Item<Real>::NotPresentedResponse();
02120 for (; n--; ++ioff, ++ilen, ++ir)
02121 {
02122
02123 char *pos = line + *ioff + *ilen - 1;
02124 *ir = 0;
02125 int power = 1;
02126 for (int i=*ilen; i--; power *= 10, --pos)
02127 {
02128 if (*pos == np)
02129 {
02130 *ir = -1;
02131 break;
02132 }
02133 else if ( (*pos < '0') && (*pos > '9'))
02134 {
02135 char errstr[50];
02136 std::sprintf(errstr, "Invalid item response: %1c", *pos);
02137 gEtirmRun->returnString = errstr;
02138 throw RuntimeError((gEtirmRun->returnString).c_str(), fname);
02139 }
02140 *ir += power * (*pos - '0');
02141 }
02142 }
02143
02144 return resp;
02145 }
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165 int_vector *get_responses_missing(char *line, int_vector *offset, int_vector *len,
02166 int_vector *items)
02167 {
02168 const char *fname = "get_responses_missing";
02169 CheckRunInit();
02170
02171 int n = offset->size();
02172
02173 if (n != len->size() || n != items->size())
02174 {
02175 throw InvalidArgument("Lengths of vector arguments do not match", fname);
02176 }
02177
02178 int_vector *resp = get_responses(line, offset, len);
02179
02180
02181 int nall = gEtirmRun->numItems;
02182 int_vector *allresp = new int_vector(nall, -1);
02183
02184
02185 int_vector::iterator ir = resp->begin();
02186 int_vector::iterator ii = items->begin();
02187 for (; n--; ++ii, ++ir)
02188 {
02189 if ( (*ii < 1) || (*ii > nall))
02190 {
02191 delete resp;
02192 throw InvalidArgument("Invalid item number", fname);
02193 }
02194 (*allresp)[*ii-1] = *ir;
02195 }
02196
02197 delete resp;
02198
02199 return allresp;
02200 }
02201
02202 }
02203