C:/programs/etirm/src/Start3PL.h

Go to the documentation of this file.
00001 /*! \file Start3PL.h
00002  
00003   \brief
00004   Compute item parameter estimate starting values for one, two, or
00005   three-parameter logistic model using nonlinear regression for each item
00006   based on an estimated ability for each examinee. Ability estimates
00007   are obtained using the PROX method.
00008 
00009   Estimation Toolkit for Item Response Models (ETIRM)
00010   http://www.smallwaters.com/software/cpp/etirm.html
00011 
00012   Author(s): 
00013   Werner Wothke, maintenance (http://www.smallwaters.com)
00014   Brad Hanson (http://www.b-a-h.com/)
00015   See the file LICENSE for information on usage and redistribution.
00016 
00017   Copyright (C) 2008, Werner Wothke
00018   Copyright (c) 2000-2001, Bradley A. Hanson
00019  */
00020 
00021 #ifndef ETIRM_START3PL_H_
00022 #define ETIRM_START3PL_H_
00023 
00024 #ifdef ETIRM_NO_DIR_PREFIX
00025 #include "etirmtypes.h"
00026 #else
00027 #include "etirm/etirmtypes.h"
00028 #endif
00029 
00030 #include <set>
00031 #include <cmath> // for log, sqrt, fabs
00032 // for compilers which do not put C library functions in std namespace
00033 #ifdef BOOST_NO_STDC_NAMESPACE
00034 namespace std
00035 { using ::sqrt; using ::log; using ::fabs;}
00036 #endif
00037 
00038 namespace etirm
00039 {
00040 
00041   const Real invalidLogit = 10000.0; 
00042   //!< value to indicate invalid logit (e.g., logit(1))
00043 
00044   /*!
00045     \brief
00046     Compute mean and standard deviation of logit item difficulty over items 
00047     responded to by an examinee.
00048    
00049     \section template_args Template Parameters
00050    
00051     \param RI Type of iterator over examinee responses (iterator returned 
00052         by responses_begin() for an Examinee object)
00053     \param II Type of iterator over items (iterator over pointers to Item objects)
00054 
00055     \section function_args Function Parameters
00056    
00057     \param[in] resp Iterator pointing to first response of examinee.
00058     \param[in] iitem  Iterator pointing to first item.
00059     \param[in] itemdiff Item difficulties.
00060     \param[in] notPresentedResponse Response which indicates an item was not 
00061         presented to an examinee. Assumed to be the same for all items.
00062     \param[out] mean  Mean of abilities for persons responding to the item.
00063     \param[out] variance  Variance of abilities for persons responding to the item.
00064    */
00065   template <class RI, class II> void PersonMoments(RI iresp, II iitem, RealVector &itemdiff,
00066       Response notPresentedResponse, Real *mean, Real *variance)
00067   {
00068 
00069     /* Compute logit of examinee proportion correct scores */
00070     RealVector::iterator idiff = itemdiff.begin();
00071     int total = 0;
00072     *mean = 0.0;
00073     *variance = 0.0;
00074     for (int i = itemdiff.size(); i--; ++iitem, ++idiff)
00075     {
00076       Response resp = iresp[(*iitem)->Index()];
00077       if (resp != notPresentedResponse && *idiff != invalidLogit)
00078       {
00079         *mean += *idiff;
00080         *variance += *idiff * *idiff;
00081         ++total;
00082       }
00083     }
00084 
00085     *mean /= total;
00086     *variance /= total;
00087     *variance -= *mean * *mean;
00088   }
00089 
00090   /*!
00091     \brief
00092     Compute mean and standard deviation of person ability over examinees
00093     who reponded to an item.
00094    
00095     \section template_args Template Parameters
00096    
00097     \param EI  Type of iterator over examinees (iterator over pointers to Examinee objects)
00098     \param RI Type of iterator over examinee responses (iterator returned by responses_begin() for an Examinee object)
00099    
00100     \section function_args Function Parameters
00101    
00102     \param[in] num_examinees  Number of examinees.
00103     \param[in] begin_examinee Iterator to pointer to first examinee.
00104     \param[in] item Index of item in response string to compute moments for (0 offset).
00105     \param[in] &abilities  Address of ability vector for all persons.
00106     \param[in] notPresentedResponse Response which indicates an item was not presented
00107        to an examinee. Assumed to be the same for all items.
00108     \param[out] mean  Mean of abilities for persons resonding to the item.
00109     \param[out] variance  Variance of abilities for persons resonding to the item.
00110    */
00111   template <class IE, class RI> void ItemMoments(int num_examinees, IE begin_examinee, int item,
00112       RealVector &abilities, Response notPresentedResponse, double *mean, double *variance)
00113   {
00114     /* Compute logit of examinee proportion correct scores */
00115     RealVector::iterator iabil = abilities.begin();
00116     IE ie = begin_examinee;
00117     Real total = 0;
00118     *mean = 0.0;
00119     *variance = 0.0;
00120     for (int i = num_examinees; i--; ++ie, ++iabil)
00121     {
00122       RI resp = (*ie)->responses_begin() + item;
00123       Real count = (*ie)->Count();
00124 
00125       if (*resp != notPresentedResponse && *iabil != invalidLogit)
00126       {
00127         *mean += *iabil * count;
00128         *variance += *iabil * *iabil * count;
00129         total += count;
00130       }
00131     }
00132 
00133     *mean /= total;
00134     *variance /= total;
00135     *variance -= *mean * *mean;
00136   }
00137 
00138   /*!
00139     \brief
00140     Compute Rasch item difficulties and examinee abilities using the Normal
00141     Approximation Estimation Algorithm (PROX). 
00142     
00143     The scale of the latent variable is set such that the sum of the item 
00144     difficulties is zero.
00145     
00146     For information on PROX see
00147    
00148     Linacre, J. M. (1994). PROX with missing data. Rasch Measurement
00149         Transactions, 8(3), 378.
00150    
00151     Cohen, L. (1979). Approximate expressions for parameter estimates in the Rasch model.
00152         British Journal of Mathematical and Statistical Psychology, 32(1), 113-120.
00153    
00154     \section template_args Template Parameters
00155        
00156     \param  EI  Type of iterator over examinees (iterator over pointers to Examinee 
00157         objects).
00158     \param  RI  Type of iterator over examinee responses (iterator returned by 
00159         responses_begin() for an Examinee object).
00160     \param  II  Type of iterator over items (iterator over pointers to Item objects).
00161 
00162     \section function_args Function Parameters
00163    
00164     \param[in]  numItems  Number of items.
00165     \param[in]  useAll  If true calculate PROX estimates for all examinees and items, 
00166         even examinees who get all items right or all items wrong, and even for items 
00167         answered all correctly or all incorrectly.
00168     \param[in]  begin_examinee  Iterator to pointer to first examinees.
00169     \param[in]  end_examinee  Iterator to pointer to one past last examinees.
00170     \param[in]  begin_item  Iterator to pointers to first item.
00171     \param[in]  notPresentedResponse  Response which indicates an item was not 
00172         presented to an examinee. Assumed to be the same for all items.
00173     \param[out] itemdiff  Item difficulties.
00174     \param[out] abilities Examinee abilities.
00175    */
00176   template <class EI, class RI, class II> void PROX(int numItems, bool useAll, EI begin_examinee,
00177       EI end_examinee, II begin_item, Response notPresentedResponse, RealVector &itemdiff,
00178       RealVector &abilities)
00179   {
00180     const int maxIter = 10; // maximum number of iterations for PROX algorithm
00181     const double convergenceCrit = 0.01; // if maximum difference in examinee abilities is less then this
00182     // over consecutive iterations then stop
00183     int i, iitem;
00184     int num_examinees = end_examinee - begin_examinee;
00185     RealVector logitDiff(numItems);
00186     RealVector logitAbility(num_examinees);
00187 
00188     /* Compute logit of item difficulties */
00189     RealVector::iterator ilogit = logitDiff.begin();
00190     for (i=0; i<numItems; ++i, ++ilogit)
00191     {
00192       Real total = 0.0;
00193       Real sum = 0.0;
00194       EI ie = begin_examinee;
00195       int nvalid = 0;
00196       iitem = begin_item[i]->Index();
00197       Response correct = begin_item[i]->CorrectResponse();
00198       while (ie != end_examinee)
00199       {
00200         RI ir = (*ie)->responses_begin() + iitem;
00201         if (*ir != notPresentedResponse)
00202         {
00203           if (*ir == correct)
00204             sum += (*ie)->Count();
00205           total += (*ie)->Count();
00206           ++nvalid;
00207         }
00208         ++ie;
00209       }
00210 
00211       if (total == 0.0)
00212         throw RuntimeError("No valid responses for an item", "PROX");
00213 
00214       if (sum == 0.0 || sum == total)
00215       {
00216         if (useAll)
00217         {
00218           Real halfCount = total / (2*nvalid); // 1/2 average count per examinee (usually 0.5)
00219           Real maxLogit = std::log(halfCount / (total-halfCount));
00220 
00221           /* Use sum = halfcount if sum == 0.0 and use sum = total - halfCount if sum == total */
00222           *ilogit = (sum == 0.0) ? maxLogit : (1.0 / maxLogit);
00223         }
00224         else
00225         {
00226           *ilogit = invalidLogit;
00227         }
00228       }
00229       else
00230       {
00231         *ilogit = std::log(sum / (total-sum));
00232       }
00233     }
00234 
00235     /* Compute logit of examinee proportion correct scores */
00236     ilogit = logitAbility.begin();
00237     for (EI ie = begin_examinee; ie != end_examinee; ++ie, ++ilogit)
00238     {
00239       Real total = 0.0;
00240       Real sum = 0.0;
00241       II item = begin_item;
00242       RI bresp = (*ie)->responses_begin();
00243       for (i=numItems; i--; ++item)
00244       {
00245         Response resp = bresp[(*item)->Index()];
00246         if (resp != notPresentedResponse)
00247         {
00248           if (resp == (*item)->CorrectResponse())
00249             ++sum;
00250           ++total;
00251         }
00252       }
00253 
00254       if (total == 0.0)
00255       {
00256         *ilogit = invalidLogit;
00257       }
00258       else if (sum == 0.0 || sum == total)
00259       {
00260         if (useAll)
00261         {
00262           /* Use sum = 0.5 if sum == 0.0 and use sum = total - 0.5 if sum == total */
00263           *ilogit = (sum == 0.0) ? (std::log(0.5 / (total-0.5))) : std::log((total - 0.5) / 0.5);
00264         }
00265         else
00266         {
00267           *ilogit = invalidLogit;
00268         }
00269       }
00270       else
00271       {
00272         *ilogit = std::log(sum / (total-sum));
00273       }
00274     }
00275 
00276     int iter;
00277     double mean = 0.0;
00278     double variance = 1.0;
00279     RealVector prevAbility(abilities); // ability estimates at previous iteration - used to check for convergence
00280     for (iter=0; iter<maxIter; ++iter)
00281     {
00282       /* Compute difficulties for each item */
00283       RealVector::iterator idiff = itemdiff.begin();
00284       ilogit = logitDiff.begin();
00285       Real sum = 0.0;
00286       int nvalid = 0;
00287       for (i=0; i<numItems; ++i, ++ilogit, ++idiff)
00288       {
00289         if (*ilogit != invalidLogit)
00290         {
00291           /* Compute mean and variance of abilities for persons responding to item i */
00292           if (iter > 0) // mean and variance of item difficulties set to 0 and 1 for first iteration
00293           {
00294             iitem = begin_item[i]->Index();
00295             ItemMoments<EI, RI>(num_examinees, begin_examinee, iitem, abilities,
00296                 notPresentedResponse, &mean, &variance);
00297           }
00298 
00299           /* Compute new item difficulty */
00300           *idiff = mean - std::sqrt(1 + variance/2.9) * *ilogit;
00301           sum += *idiff;
00302 
00303           ++nvalid;
00304         }
00305       }
00306 
00307       /* adjust item difficulties to sum to zero */
00308       sum /= nvalid;
00309       idiff = itemdiff.begin();
00310       for (i = numItems; i--; ++idiff)
00311       {
00312         if (*idiff != invalidLogit)
00313           *idiff -= sum;
00314       }
00315 
00316       /* Compute abilities for each examinee */
00317       RealVector::iterator iabil = abilities.begin();
00318       ilogit = logitAbility.begin();
00319       for (EI ie = begin_examinee; ie != end_examinee; ++ie, ++iabil, ++ilogit)
00320       {
00321         if (*ilogit != invalidLogit)
00322         {
00323           /* Compute mean and variance of item difficulties for items person responded to */
00324           PersonMoments<RI, II>((*ie)->responses_begin(), begin_item, itemdiff, notPresentedResponse, &mean, &variance);
00325 
00326           /* Compute new person ability */
00327           *iabil = mean + std::sqrt(1 + variance/2.9) * *ilogit;
00328         }
00329       }
00330 
00331       /* Check if abilities have converged */
00332       if (iter > 0)
00333       {
00334         Real maxdiff = 0.0;
00335         for (i=0; i<num_examinees; ++i)
00336         {
00337           if (abilities[i] != invalidLogit)
00338           {
00339             Real diff = std::fabs(abilities[i] - prevAbility[i]);
00340             if (diff > maxdiff)
00341               maxdiff = diff;
00342           }
00343         }
00344         if (maxdiff < convergenceCrit)
00345           break;
00346       }
00347       prevAbility = abilities;
00348     }
00349   }
00350 
00351   /*! 
00352     \brief
00353     Assigns individual examinee thetas into discrete latent variable
00354     categories and updates expected counts n and r for item M-step.
00355    
00356     Given category values of the discrete latent variable as 
00357     c_1, c_2, ..., c_ncat, classifies individual thetas into categories 
00358     using ncat-1 cutpoints (c_1+c_2)/2, (c_2+c_3)/2,..., where the 
00359     examinee is classified into the first category if the theta value 
00360     is less than (c_1+c_2)/2, into the second category if their theta 
00361     value is greater than or equal to (c_1+c_2)/2 and less than 
00362     (c_2+c_3)/2, etc.
00363     
00364     \section template_args Template Parameter
00365    
00366     \param I  Item type.
00367    
00368     \section function_args Function Parameters
00369    
00370     \param[in,out]  n Number of examinees who respond to the item on input, 0 on output.
00371     \param[in]  itemTheta Vector of thetas for examinees who reponded to an item.
00372     \param[in,out]  nVec  Iterator to vector of expected item response counts for each theta value?
00373     \param[in,out]  rVec  Iterator to vector of expected number correct counts for each theta value?.
00374     \param[in,out]  *item Pointer to item object.
00375    */
00376   template <class I> void AssignItemNR(int n, RealVector::iterator itemTheta,
00377       RealVector::iterator nVec, RealVector::iterator rVec, I *item)
00378   {
00379     int i;
00380 
00381     int ncat = item->NumLatentVarCat();
00382 
00383     if (ncat == 0)
00384       throw RuntimeError("Values of discrete latent variable categories are missing for an item",
00385           "AssignItemNR");
00386 
00387     /* Compute cutpoints for categorizing individual latent variable values */
00388     RealVector cutpoints(ncat-1);
00389     RealVector::iterator ic = cutpoints.begin();
00390     typename I::point_iterator ip = item->GetLatentVarPoints(1); // use points for first group
00391     for (i=ncat-1; i--; ++ic, ++ip)
00392     {
00393       *ic = (ip[0] + ip[1]) / 2.0;
00394     }
00395 
00396     item->InitializeNR();
00397     typename I::n_iterator in = item->NVector();
00398     typename I::r_iterator ir = item->RVector(item->CorrectResponse());
00399     for (; n--; ++itemTheta, ++nVec, ++rVec)
00400     {
00401       /* find category for theta using inefficient linear search */
00402       ic = cutpoints.begin();
00403       for (i=0; i<ncat-1; ++i, ++ic)
00404       {
00405         if (*itemTheta < *ic)
00406           break;
00407       }
00408 
00409       in[i] += *nVec;
00410       ir[i] += *rVec;
00411     }
00412   }
00413 
00414   /*!
00415     \brief
00416     Computes starting values for a sequence of items modeled with the
00417     three-parameter logistic model. 
00418     
00419     Nonlinear regression is employed for each item, treating the theta estimate for 
00420     each person as the independent variable and the item responses as the dependent
00421     variable. Theta estimates and initial b parameters for the nonlinear regression 
00422     are calculated using the PROX procedure. Theta estimates for each person are 
00423     categorized using latent variable categories defined for each item (using the
00424     interface of class ItemNR).
00425    
00426     Returns the number of times minimization procedure failed while using nonlinear 
00427     regression. Nonconvergence after the maximum number of iterations has been 
00428     exceeded is not considered a failure.
00429    
00430     \section template_args Template Parameters
00431 
00432     \param RI Type of iterator over examinee responses (iterator returned by 
00433         responses_begin() for an Examinee object).
00434     \param MI Type of iterator over minimization routines used for each item.
00435     \param EI Type of iterator over examinees (iterator over pointers to 
00436         Examinee objects).
00437     \param I  Item type.
00438     \param II Type of iterator over items (iterator over pointers to Item objects).
00439    
00440     \section function_args Function Parameters
00441    
00442     \param[in]  begin_min Iterator to pointers to minimization routines used for items.
00443          These should correspond to the items given by begin_item and end_item that 
00444          are in the set calc_items.
00445     \param[in]  begin_examinee  Iterator to pointer to the first examinee.
00446     \param[in]  end_examinee    Iterator to pointer to one past the last examinee. 
00447     \param[in,out]  begin_item  Iterator to pointer to the first item.
00448     \param[in,out]  end_item  Iterator to pointer to one past the last item.   
00449         All these items are used in computing PROX estimates of examinee 
00450         abilities. Starting values are computed for any of these items that are 
00451         also in the set calc_items. On output the item parameter estimates for each 
00452         item also present in calc_items are set to the starting values calculated 
00453         in this function. 
00454     \param[in]  notPresentedResponse  Response which indicates an item was not 
00455         presented to an examinee. Assumed to be the same for all items.
00456     \param[in]  useAll  If true calculate PROX estimates for all examinees and 
00457         items, even examinees who get all items right or all items wrong, and 
00458         even for items answered all correctly or all incorrectly.
00459     \param[in]  baseGroup Number of group to use as base group where mean and 
00460         s.d. of latent variable distribution are zero and one.
00461     \param[in]  calc_items  Set containing items for which starting values are 
00462         computed. All items given by begin_item and end_item are used to compute 
00463         PROX estimates of examinee ability, but starting values are only 
00464         calculated for items in calc_items. If calc_items is null then starting 
00465         values are computed for all items given by begin_item and end_item.
00466   */
00467   template <class RI, class MI, class EI, class I, class II> int StartingValues3PL(MI begin_min,
00468       EI begin_examinee, EI end_examinee, II begin_item, II end_item,
00469       Response notPresentedResponse, bool useAll = false, int baseGroup = 1,
00470       std::set<I *> *calc_items = 0)
00471   {
00472 
00473     int numExaminees = end_examinee - begin_examinee;
00474     int numItems = end_item - begin_item;
00475 
00476     RealVector thetas(numExaminees, invalidLogit);
00477     RealVector itemDiff(numItems, invalidLogit);
00478 
00479     typedef std::vector<Response> cvector;
00480 
00481     /* Compute PROX estimates of examinee ability and item difficulty */
00482     PROX<EI, RI, II>(numItems, useAll, begin_examinee, end_examinee, begin_item,
00483         notPresentedResponse, itemDiff, thetas);
00484 
00485     /* Compute mean of PROX estimates of examinee ability in base group and assign case weights */
00486     int i;
00487     RealVector nVec(numExaminees); // store case weights to use in regression
00488     RealVector::iterator in = nVec.begin();
00489     RealVector::iterator itheta = thetas.begin();
00490     Real mean = 0.0;
00491     Real nwt = 0.0;
00492     EI ie = begin_examinee;
00493     for (i = numExaminees; i--; ++in, ++itheta, ++ie)
00494     {
00495       *in = (*ie)->Count();
00496       if ((*ie)->Group() == baseGroup && *itheta != invalidLogit)
00497       {
00498         mean += *itheta * *in;
00499         nwt += *in;
00500       }
00501     }
00502     if (nwt == 0)
00503       throw RuntimeError("No examinees with valid item responses in base group",
00504           "StartingValues3PL");
00505 
00506     mean /= nwt;
00507 
00508     /* Compute standard deviation of PROX estimates of examinee ability in base group */
00509     Real sd = 0.0;
00510     itheta = thetas.begin();
00511     in = nVec.begin();
00512     ie = begin_examinee;
00513     for (i = numExaminees; i--; ++in, ++itheta, ++ie)
00514     {
00515       if ((*ie)->Group() == baseGroup && *itheta != invalidLogit)
00516       {
00517         Real diff = *itheta - mean;
00518         sd += diff * diff * *in;
00519       }
00520     }
00521     sd /= nwt;
00522     sd = std::sqrt(sd);
00523 
00524     /* Put thetas on latent variable scale so mean and s.d. of thetas for examinees in base group are 0 and 1 */
00525     itheta = thetas.begin();
00526     for (i=numExaminees; i--; ++itheta)
00527     {
00528       if (*itheta != invalidLogit)
00529       {
00530         *itheta -= mean;
00531         *itheta /= sd;
00532       }
00533     }
00534 
00535     /* Put b parameters on latent variable scale so mean and s.d. of thetas for examinees in base group are 0 and 1 */
00536     RealVector::iterator idiff = itemDiff.begin();
00537     for (i = numItems; i--; ++idiff)
00538     {
00539       if (*idiff != invalidLogit)
00540       {
00541         *idiff -= mean;
00542         *idiff /= sd;
00543       }
00544     }
00545 
00546     RealVector itemTheta(numExaminees); // vector of thetas for examinees who reponded to an item
00547     RealVector rVec(numExaminees); // count of number of correct answers for each theta value 
00548     // (r vector in M-step computation)
00549     // nVec holds count for each theta value (n vector in M-step computation)
00550 
00551     /* Compute starting values for each item */
00552     int minError = 0; // Count of number of time minimization failed in computing regression
00553     for (int item = 0; item < numItems; ++item, ++begin_item)
00554     {
00555       if (calc_items)
00556       {
00557         if (calc_items->find(*begin_item) == calc_items->end())
00558           continue;
00559       }
00560 
00561       /* Create vectors of item responses and thetas for item */
00562       EI ie = begin_examinee;
00563       RealVector::iterator it = itemTheta.begin();
00564       in = nVec.begin();
00565       RealVector::iterator ir = rVec.begin();
00566       RealVector::iterator alltheta = thetas.begin();
00567       int n = 0; // number of examinees who respond to the item
00568       nwt = 0.0; // weighted number of examinees who respond to the item
00569       Real pvalue = 0.0;
00570       Response correct = (*begin_item)->CorrectResponse();
00571       while (ie != end_examinee)
00572       {
00573         RI iresp = (*ie)->responses_begin() + (*begin_item)->Index();
00574         if (*iresp != notPresentedResponse && *alltheta != invalidLogit)
00575         {
00576           *it = *alltheta;
00577           *in = (*ie)->Count();
00578           nwt += *in;
00579           if (*iresp == correct)
00580           {
00581             pvalue += *in;
00582             *ir = *in;
00583           }
00584           else
00585           {
00586             *ir = 0.0;
00587           }
00588           ++n;
00589           ++it;
00590           ++in;
00591           ++ir;
00592         }
00593         ++alltheta;
00594 
00595         ++ie;
00596       }
00597       pvalue /= nwt;
00598 
00599       /* Compute starting values for item */
00600       int numParameters = (*begin_item)->NumParameters();
00601       RealVector start(numParameters);
00602       Real startb = itemDiff[item]; // use b from PROX as starting value
00603 
00604       if (numParameters > 1)
00605       {
00606         // PROX estimate assumes D=1.0, so if D for item is different from
00607         // 1.0 adjust the a-parameter.
00608         start(1) = 1.0 / (*begin_item)->NormalizingConstant();
00609         start(2) = startb;
00610       }
00611       else
00612       {
00613         start(1) = startb;
00614       }
00615 
00616       /* Make starting c parameter slightly larger than zero since prior density of c
00617        is zero when c is equal to zero */
00618       if (numParameters > 2)
00619         start(3) = 0.05;
00620 
00621       if (pvalue == 1.0 || pvalue == 0.0)
00622       {
00623         if (!useAll)
00624         {
00625           /* If all responses to an item are correct or incorrect and useAll is false then PROX
00626            estimate of b will not exist, so use logit of number correct score 1/2 different from zero
00627            or perfect as b starting value. */
00628           Real maxlogit = std::log((numExaminees - 0.5) / 0.5);
00629           startb = (pvalue == 1.0) ? maxlogit : 1.0/maxlogit;
00630           if (numParameters > 1)
00631             start(2) = startb;
00632           else
00633             start(1) = startb;
00634         }
00635         (*begin_item)->NonZeroPriors(start);
00636         (*begin_item)->SetParameters(start);
00637       }
00638       else
00639       {
00640         /* Use nonlinear regression to find starting values */
00641 
00642         /* Assign expected counts n and r for item */
00643         AssignItemNR<I>(n, itemTheta.begin(), nVec.begin(), rVec.begin(), *begin_item);
00644 
00645         (*begin_min)->SetFunction(*begin_item);
00646 
00647         RealVector xpls(numParameters), gpls(numParameters);
00648         double fpls;
00649 
00650         /* Modify starting values which for which prior density is zero */
00651         (*begin_item)->NonZeroPriors(start);
00652 
00653         int result = (*begin_min)->Minimize(start, xpls, fpls, gpls);
00654 
00655         // assign values computed if minimization succeeded 
00656         // or failed because of the maximum number of iterations
00657         // being exceeded without convergence
00658         if (!result || (*begin_min)->GetMessage() == 4)
00659         {
00660           (*begin_item)->SetParameters(xpls);
00661         }
00662         else // if minimization failed use initial starting value for b
00663         {
00664           start(1) = 1.0;
00665           start(3) = 0.1;
00666           (*begin_item)->SetParameters(start);
00667           minError++;
00668         }
00669       }
00670       ++begin_min; // only increment for items for which starting values are computed
00671     }
00672     return minError;
00673   }
00674 
00675 #endif // ETIRM_START3PL_H_
00676 } // namespace etirm

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