Geez, that is cool.  Thanks Dave, this is a great way to do code<div>testing.  I'll work on this tomorrow or you can commit the fix.</div><div><br></div><div>Johnoel<br><div><br></div><div>On Wed, Apr 4, 2012 at 2:14 PM, dave fournier <span dir="ltr"><<a href="mailto:davef@otter-rsch.com" target="_blank">davef@otter-rsch.com</a>></span> wrote:</div>
<div><div><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
At our workshop Mark pointed out some problem with the init_number_vector class for RE models.<br>
I have identified some serious problems that are not so easy to fix so I wondered if, as an exercise<br>
it would be easy to use some C++ capabilities to introduce a new class which works better,<br>
without having to modify the existing code.  This sort of programming typically uses virtual<br>
functions.<br>
<br>
One starts with the  df1b2_init_vector class which is what gets invoked when you use an init_vector<br>
in an RE model. Now the problem with a df1b2_init_vector is that it only<br>
has an int for its starting phase.  Since we want the different elements<br>
of the vector to have their own starting phase we will add that to the class.<br>
Sow we derive a new   class xdf1b2_init_number_vector from<br>
public df1b2_init_vector and add what we need to it.<br>
<br>
class xdf1b2_init_number_vector : public df1b2_init_vector<br>
{<br>
    index_type * it;<br>
<br>
   // ... other stuff<br>
<br>
};<br>
<br>
all that is needed is a pointer to index_type.  This will permit the use<br>
of a vector or a number to specify the starting phases. If a number is used<br>
they will all be the same.<br>
<br>
Now what you can do is to use the class in a toy program.<br>
Start with a tpl file like this.<br>
******************************<u></u>**************************<br>
******************************<u></u>**************************<br>
<br>
DATA_SECTION<br>
  int n<br>
 !! n=2;<br>
 ivector st(1,n)<br>
 !! st(1)=1;<br>
 !! st(2)=-1;<br>
<br>
<br>
PARAMETER_SECTION<br>
  init_number_vector beta(1,n,st)<br>
  random_effects_vector eps(1,1)<br>
<br>
  objective_function_value f<br>
<br>
PROCEDURE_SECTION<br>
  f+=0.5*norm2(eps);<br>
  for (int i=1;i<=n;i++)<br>
  {<br>
    f+= square(beta(i)-1.0);<br>
  }<br>
<br>
GLOBALS_SECTION<br>
<br>
<br>
#include <admodel.h><br>
  #include <df1b2fun.h><br>
  #include <adrndeff.h><br>
  class xdf1b2_init_number_vector : public df1b2_init_vector<br>
  {<br>
    index_type * it;<br>
  public:<br>
    xdf1b2_init_number_vector(<u></u>void);<br>
<br>
    void allocate(int imin,int imax,const index_type& ps,char * s)<br>
    {<br>
      df1b2_init_vector::allocate(<u></u>imin,imax,s);<br>
      it=new index_type(ps);<br>
    }<br>
<br>
  };<br>
<br>
  xdf1b2_init_number_vector::<u></u>xdf1b2_init_number_vector(<u></u>void):<br>
    df1b2_init_vector()<br>
  {<br>
    it=0;<br>
  }<br>
<br>
******************************<u></u>**************************<br>
******************************<u></u>**************************<br>
******************************<u></u>**************************<br>
******************************<u></u>**************************<br>
<br>
Run tpl2rem on this tpl file and change<br>
<br>
  df1b2_init_number_vector  to  xdf1b2_init_number_vector<br>
<br>
in the cpp and htp files and compile with debug and safe mode.<br>
When you run the model you will ifnd that it runs out of an array<br>
in<br>
    void df1b2_init_vector set_value(const init_df1b2vector& _x,const int& _ii,<br>
      const df1b2variable& pen);<br>
<br>
The reason is that it is using the starting phase number from that class.<br>
To change that behaviour we just need override the set_value function<br>
with a new one in the derived class. It looks like this.<br>
<br>
<br>
<br>
  void xdf1b2_init_number_vector::<u></u>set_value(const init_df1b2vector& x,<br>
    const int& _ii,const df1b2variable& pen)<br>
  {<br>
    ADUNCONST(int,ii)<br>
    int mmin=indexmin();<br>
    int mmax=indexmax();<br>
    for (int i=mmin;i<=mmax;i++)<br>
    {<br>
      if (withinbound(0,ad_integer((*<u></u>it)(i)),current_phase))<br>
        (*this)(i) = (x(ii++));<br>
    }<br>
  }<br>
<br>
The change is<br>
<br>
  if (withinbound(0,ad_integer((*<u></u>it)(i)),current_phase)<br>
<br>
which has been added to the function.<br>
The class declaration is extended to<br>
<br>
  class xdf1b2_init_number_vector : public df1b2_init_vector<br>
  {<br>
    index_type * it;<br>
  public:<br>
    xdf1b2_init_number_vector(<u></u>void);<br>
<br>
    void allocate(int imin,int imax,const index_type& ps,char * s)<br>
    {<br>
      df1b2_init_vector::allocate(<u></u>imin,imax,s);<br>
      it=new index_type(ps);<br>
    }<br>
    virtual void set_value(const init_df1b2vector& _x,const int& _ii,<br>
      const df1b2variable& pen);<br>
  };<br>
<br>
It seems to work, although there may be some other functions which will need<br>
to be overridden as well.<br>
<br>
What's my point?  Well no planning or committees were needed. All I had<br>
to do was to run the code with the debugger and it told me what to do. Entire<br>
process took about two hours.<br>
<br>
Time for a drink.<br>
<br>
<br>
______________________________<u></u>_________________<br>
Developers mailing list<br>
<a href="mailto:Developers@admb-project.org" target="_blank">Developers@admb-project.org</a><br>
<a href="http://lists.admb-project.org/mailman/listinfo/developers" target="_blank">http://lists.admb-project.org/<u></u>mailman/listinfo/developers</a><br>
</blockquote></div><br></div>
</div>
</div>