Example #1
0
/*!
  \brief Creates a \c GMRFLib_optimize_param_tp -object holding the default settings.

  \param[out] optpar A pointer to a \c GMRFLib_optimize_param_tp pointer. 
  At output the \c GMRFLib_optimize_param_tp -object contains the default values.

  \par Description of elements in \c GMRFLib_optimize_param_tp -object:
  \n \em fp: A file for printing output from the optimizer. \n
  <b>Default value: \c NULL</b> \n\n
  \em opt_type: The type of optimizer to be used. Four methods are available.\n
  <b>Default value: #GMRFLib_OPTTYPE_SAFENR</b> \n\n
  \em nsearch_dir: Indicates the number of previously search gradient directions 
  on which the current search direction should be orthogonal (using the conjugate
  gradient (CG) method). \n
  <b>Default value: 1</b> \n\n
  \em restart_interval: If <em>restart_interval = r </em>,
  the CG search will be restarted every <em>r</em>'th iteration. \n
  <b>Default value: 10</b> \n\n
  \em max_iter:  The maximum number of iterations. \n
  <b>Default value: 200</b> \n\n
  \em fixed_iter: If > 0, then this fix the number of iterations, whatever 
  all other stopping-options. \n
  <b>Default value: 0</b> \n\n
  \em max_linesearch_iter: The maximum number of iterations within each search 
  direction (CG). \n
  <b>Default value: 200</b> \n\n
  \em step_len: Step length in the computation of a Taylor expansion or second 
  order approximation of the log-likelihood around a point 
  <em> \b x_0</em> (CG and NR). \n
  <b>Default value: 1.0e-4</b> \n\n
  \em abserr_func: The absolute error tolerance for the value of the function 
  to be optimized (CG and NR). \n
  <b>Default value: 0.5e-3</b> \n\n
  \em abserr_step: The absolute error tolerance, relative to the number of nodes, 
  for the size of one step of the optimizer (CG and NR). \n
  <b>Default value: 0.5e-3</b> \n
 */
int GMRFLib_default_optimize_param(GMRFLib_optimize_param_tp **optpar)
{

    /* 
       define default values for the optimizer.
       methods are

             GMRFLib_OPTTYPE_NR : newton-raphson               O(n^1.5) - O(n^2)
	     GMRFLib_OPTTYPE_CG : conjugate gradient method    O(n log(n)) or so
     */
    
    GMRFLib_ASSERT(optpar, GMRFLib_EINVARG);
    *optpar = Calloc(1, GMRFLib_optimize_param_tp); MEMCHK(*optpar);

    (*optpar)->fp                  = NULL;
    (*optpar)->opt_type            = GMRFLib_OPTTYPE_SAFENR; 
    (*optpar)->nsearch_dir         = 1;
    (*optpar)->restart_interval    = 10;
    (*optpar)->max_iter            = 200;
    (*optpar)->fixed_iter          = 0;		  /* default: do not use */
    (*optpar)->max_linesearch_iter = 200;
    (*optpar)->step_len            = 1.0e-4;
    (*optpar)->abserr_func         = 0.5e-3;
    (*optpar)->abserr_step         = 0.5e-3;

    return GMRFLib_SUCCESS;
}
Example #2
0
/*!

  \brief Computes the graph corresponding to the precision matrix <em>\b Q</em> based on the weight
  function.

  This function converts a graph definition on the weights \f$ w_{ij} \f$ of a weighted average GMRF
  model, as defined by <b>(GMRF-8)</b> in \ref specification, to the graph defining the precision
  matrix <em>\b Q</em> of the GMRF <em>\b x</em>.

  \param[out] wa_problem At output, \a wa_problem is allocated as a pointer to a \c
  GMRFLib_wa_problem_tp, holding the graph of the GMRF <em>\b x</em>, the function defining the
  <em>\b Q</em> -matrix and a \em character -pointer holding the address of the variable or data
  structure holding it's arguments.

  \param[in] wagraph The graph of the weights \f$ {w_{ij}} \f$ in the density function of <em>\b
  x</em>, of the form <b>(GMRF-8)</b>.

  \param[in] wafunc A pointer to a function returning the weights \f$ w_{ij} \f$. The function is to
  be of the same format as the function defining the elements of the <em>\b Q</em> -matrix of a
  general GMRF, such that the argument list and return value should be the same as for the template
  \c GMRFLib_Qfunc_tp().  The arguments should be the indices \em i and \em j and a \em character
  -pointer referring to additional arguments to the function. If \f$ w_{ij}=0 \f$ initially, it is
  required to be kept unchanged.

  \param[in] wafunc_arg A \em character -pointer holding the address of a variable or data structure
  defining additional arguments to the function \a wafunc.

  \remarks Based on the weight function, defining the weights in <b>(GMRF-8)</b>, the routine
  computes the graph corresponding to the precision matrix <em>\b Q</em> of the GMRF \em x. Also,
  the function defining the elements of <em>\b Q</em> and the set of arguments (in addition to the
  indices \em i and \em j) are generated. These are returned as members of the \c
  GMRFLib_wa_problem_tp -object <em>(*problem)</em>.

  \note The weights \f$ w_{ij} \f$ that are initially defined to be 0, should be kept fixed. The
  function \c GMRFLib_prune_graph() is called on the resulting graph of the GMRF <em>\b x</em>,
  removing elements of the graph corresponding to <em>\b Q (i,j) = 0</em>.  Re-setting the zero
  weights, for example by letting the weights depend on parameters that might change while running
  the programs, will invalidate this graph reduction.\n This routine will in most cases compute
  <em>\b Q (i,j)</em> less efficiently using more memory than a tailored implementation, but may
  save you for a lot of work!!! \n There is a global variable \c GMRFLib_use_wa_table_lookup() which
  controls the internal behaviour: if it is \c #GMRFLib_TRUE (default value) then internal
  lookup-tables are build that (can really) speed up the computation, and if it is \c
  #GMRFLib_FALSE, then it does not use internal lookup-tables.  The storage requirement is \f$
  {\mathcal O}(n^{3/2}) \f$.

  \par Example:
  See \ref ex_wa
  
  \sa GMRFLib_free_wa_problem, GMRFLib_prune_graph.
 */
int GMRFLib_init_wa_problem(GMRFLib_wa_problem_tp **wa_problem, 
			    GMRFLib_graph_tp *wagraph, GMRFLib_Qfunc_tp *wafunc, char *wafunc_arg)
{
    /*
      wagraph is the graph defining

      (*) \sum_i (w_ii x_i - \sum_{j~i} w_ij x_j)^2 = x^T Q x

      where 'wafunc(i,j)' returns w_ij with arguments wafunc_arg. this routine compute the
      corresponding graph defining Q, a function returning Q_ij and its arguments.
    */

    int i, j, k, kk, jj, jjj, kkk, n, *memsiz = NULL, nnb, *hold = NULL, indx;
    GMRFLib_graph_tp *graph = NULL, *ngraph = NULL;
    GMRFLib_waQfunc_arg_tp *wa_arg = NULL;

    GMRFLib_make_empty_graph(&graph);
    n           = wagraph->n;
    graph->n    = n;
    graph->nnbs = Calloc(n, int);   MEMCHK(graph->nnbs);
    graph->nbs  = Calloc(n, int *); MEMCHK(graph->nbs);
    memsiz      = Calloc(n, int);   MEMCHK(memsiz);
     
    for(i=0;i<n;i++)
    {
	graph->nnbs[i] = wagraph->nnbs[i];
	memsiz[i]      = MAX(1, 2*graph->nnbs[i]);
	graph->nbs[i]  = Calloc(memsiz[i], int);
	if (graph->nnbs[i]) memcpy(graph->nbs[i], wagraph->nbs[i], graph->nnbs[i]*sizeof(int));
    }

    /* 
       build the new graph
    */
    if (0)
    {
	/* 
	   old code, slow algorithm.....
	*/
	for(i=0;i<n;i++)
	    for(j=0;j<wagraph->nnbs[i];j++)
		for(jj=j+1;jj<wagraph->nnbs[i];jj++)
		{
		    k  = wagraph->nbs[i][j];	
		    kk = wagraph->nbs[i][jj];	

		    if (!GMRFLib_is_neighb(k, kk, graph))
		    {
			/* 
			   add, must do it symmetrically! must also sort the neighbours, since the
			   'is_neig' function assume they are sorted.
			*/
			graph->nnbs[k]++;
			if (graph->nnbs[k] > memsiz[k])
			{
			    memsiz[k] *= 2;
			    graph->nbs[k] = (int *)realloc(graph->nbs[k], memsiz[k]*sizeof(int));
			}
			graph->nbs[k][graph->nnbs[k]-1] = kk;
			qsort(graph->nbs[k], (size_t)graph->nnbs[k], sizeof(int), GMRFLib_intcmp);

			graph->nnbs[kk]++;
			if (graph->nnbs[kk] > memsiz[kk])
			{
			    memsiz[kk] *= 2;
			    graph->nbs[kk] = (int *)realloc(graph->nbs[kk], memsiz[kk]*sizeof(int));
			}
			graph->nbs[kk][graph->nnbs[kk]-1] = k;
			qsort(graph->nbs[kk], (size_t)graph->nnbs[kk], sizeof(int), GMRFLib_intcmp);
		    }
		}
    }
    else
    {
	/* 
	   new version, runs faster, use slightly more memory, but not that much
	*/
	if (0) printf("\n\n%s:%1d:NEW CODE HERE, NOT PROPERLY TESTED!!!\n\n", __FILE__, __LINE__);
	for(i=0;i<n;i++)
	    for(j=0;j<wagraph->nnbs[i];j++)
	    {
		k  = wagraph->nbs[i][j];
		for(jj=j+1;jj<wagraph->nnbs[i];jj++)
		{
		    kk = wagraph->nbs[i][jj];	

		    if (graph->nnbs[k] >= memsiz[k])
		    {
			qsort(graph->nbs[k], (size_t)graph->nnbs[k], sizeof(int), GMRFLib_intcmp);
			for(jjj=1, kkk=0; jjj<graph->nnbs[k];jjj++)
			    if (graph->nbs[k][jjj] != graph->nbs[k][kkk]) graph->nbs[k][++kkk] = graph->nbs[k][jjj];
			graph->nnbs[k] = kkk+1;
		    }
		    if (graph->nnbs[k] >= memsiz[k])
		    {
			memsiz[k]    *= 2;
			graph->nbs[k] = (int *)realloc(graph->nbs[k], memsiz[k]*sizeof(int));
		    }
		    graph->nbs[k][graph->nnbs[k]++] = kk;

		    if (graph->nnbs[kk] >= memsiz[kk])
		    {
			qsort(graph->nbs[kk], (size_t)graph->nnbs[kk], sizeof(int), GMRFLib_intcmp);
			for(jjj=1, kkk=0; jjj<graph->nnbs[kk];jjj++)
			    if (graph->nbs[kk][jjj] != graph->nbs[kk][kkk]) graph->nbs[kk][++kkk] = graph->nbs[kk][jjj];
			graph->nnbs[kk] = kkk+1;
		    }
		    if (graph->nnbs[kk] >= memsiz[kk])
		    {
			memsiz[kk]    *= 2;
			graph->nbs[kk] = (int *)realloc(graph->nbs[kk], memsiz[kk]*sizeof(int));
		    }	
		    graph->nbs[kk][graph->nnbs[kk]++] = k;
		}
	    }
	for(i=0;i<n;i++)			  /* this step is needed */
	    if (graph->nnbs[i])
	    {
		qsort(graph->nbs[i], (size_t)graph->nnbs[i], sizeof(int), GMRFLib_intcmp);
		for(j=1, k=0;j<graph->nnbs[i];j++)
		    if (graph->nbs[i][j] != graph->nbs[i][k]) graph->nbs[i][++k] = graph->nbs[i][j];
		graph->nnbs[i] = k+1;
	    }
    }
    
    for(i=0, nnb=0;i<n;i++) nnb += graph->nnbs[i];
    if (nnb)
    {
	hold = Calloc(nnb, int); MEMCHK(hold);	  /* use a linear storage */
    }
    for(i=0, indx=0;i<n;i++) 
    {
	if (graph->nnbs[i])
	{
	    memcpy(&hold[indx], graph->nbs[i], graph->nnbs[i]*sizeof(int));
	    FREE(graph->nbs[i]);
	    graph->nbs[i] = &hold[indx]; 
	}
	else
	    FREE(graph->nbs[i]);

	indx += graph->nnbs[i];
    }

    FREE(memsiz);
    GMRFLib_prepare_graph(graph);

    /* 
       setup the new types
    */
    wa_arg              = Calloc(1, GMRFLib_waQfunc_arg_tp); MEMCHK(wa_arg);
    wa_arg->waQgraph    = graph;
    wa_arg->waQfunc     = wafunc;
    wa_arg->waQfunc_arg = wafunc_arg;
    GMRFLib_copy_graph(&(wa_arg->wagraph), wagraph); /* yes, make a copy! */

    if (GMRFLib_use_wa_table_lookup)
    {
	/* 
	   build hash table for idx = (i,j) -> neigb_info[idx]
	*/
	double idx=0.0;
	spmatrix_init_hint(&(wa_arg->neigb_idx_hash), (mapkit_size_t)GMRFLib_nQelm(graph)); /* give a hint of the size */
	wa_arg->neigb_idx_hash.alwaysdefault = 0;
	for(i=0;i<graph->n;i++)
	{
	    spmatrix_set(&(wa_arg->neigb_idx_hash), i, i, idx); idx++;
	    for(j=0;j<graph->nnbs[i];j++)
	    {
		spmatrix_set(&(wa_arg->neigb_idx_hash), i, graph->nbs[i][j], idx); idx++;
	    }
	}
	wa_arg->n_neigb_info = (int) idx;
	/* 
	   hold list of neighbors and common neigbhbors, to gain some real speedup....
	*/
	wa_arg->neigb_info = Calloc(wa_arg->n_neigb_info, GMRFLib_node_list_tp *); MEMCHK(wa_arg->neigb_info);
    }
    else
Example #3
0
bool nnToolView::readConfiguration(IXmlNode *node)
{
    int numBars;
    bool res = false;
    IXmlNode *v,*t = node->find(X("TOOLBARS"));
    if (t)
    {
        numBars=t->getLong();
    }
    else
    {
        xmlConfigurationNodeException *pe = new xmlConfigurationNodeException(X("TOOLBARS"));
        throw (pe);
    }
    if(numBars>0)
    {
        int i;
        for(i=0; i<numBars; i++)
        {
            v=t->find(X("TOOLBARS_"),i);
            if(v)
            {
                int id=0;
                IXmlNode *h=v->find(X("ID"));
                if (h)
                {
                    id=h->getLong();
                }
                else
                {
                    xmlConfigurationNodeException *pe = new xmlConfigurationNodeException(X("ID"));
                    throw (pe);
                }
                h=v->find(X("COMMANDER"));
                if(h)
                {
                    nnCommander *command= new nnCommander();
                    MEMCHK(nnCommander,command);
                    if(command)
                    {
                        res=command->readConfiguration(h);
                        if(!res)break;
                    }
                    commands[id]=command;
                }
                else
                {
                    SSTREAM ssInfo;
                    ssInfo<<X("COMMANDER");
                    xmlConfigurationNodeException *pe = new xmlConfigurationNodeException(ssInfo.str().c_str());
                    throw (pe);
                }
            }
            else
            {
                SSTREAM ss;
                ss<<X("TOOLBARS_")<<i;
                xmlConfigurationNodeException *pe = new xmlConfigurationNodeException(ss.str().c_str());
                throw (pe);
            }
        }
    }
    if(res==true)
    {
        commanderList::iterator it=commands.find(0);
        if(it!=commands.end())
        {
            active=it->second;
            active->setFont(font);
        }
        else
        {
            active=nullptr;
        }
    }
    return res;
}
Example #4
0
int GMRFLib_optimize_store(double *mode, double *b, double *c, double *mean,
			    GMRFLib_graph_tp *graph, GMRFLib_Qfunc_tp *Qfunc, char *Qfunc_args,
			    char *fixed_value, GMRFLib_constr_tp *constr, 
			    double *d, GMRFLib_logl_tp *loglFunc, char *loglFunc_arg,
			    GMRFLib_optimize_param_tp *optpar,
			    GMRFLib_store_tp *store)
{
    /* 
       locate the mode starting in 'mode' using a conjugate gradient algorithm where the search
       direction is Q-ortogonal to the m previous ones.

       exp(-0.5(x-mean)'Q(x-mean)+b'x + \sum_i d_i loglFunc(x_i,i,logl_arg)) && fixed-flags

       and linear deterministic and stochastic constaints
     */
    int sub_n, i, j, node, nnode, free_optpar, fail;
    double *cc = NULL, *initial_value = NULL;
    GMRFLib_store_tp *store_ptr;
    GMRFLib_optimize_problem_tp *opt_problem = NULL;

    GMRFLib_ENTER_ROUTINE;
    
    GMRFLib_ASSERT(graph, GMRFLib_EINVARG);
    GMRFLib_ASSERT(Qfunc, GMRFLib_EINVARG);
    
    GMRFLib_optimize_set_store_flags(store);

    /* 
       our first task, is to convert the opt_problem so we get rid of the fixed_values and then write
       the function in the canonical form

       large parts here is adapted from `problem-setup.c'!!!
    */

    /* 
       create new opt_problem
    */
    opt_problem = Calloc(1, GMRFLib_optimize_problem_tp); MEMCHK(opt_problem);

    /* 
       get the options
    */
    if (optpar)
    {
	opt_problem->optpar = optpar;
	free_optpar = 0;
    }
    else
    {
	GMRFLib_default_optimize_param(&(opt_problem->optpar));
	free_optpar = 1;
    }

    /* 
       first, find the new graph.
     */
    if (store_use_sub_graph)
    {
	/* 
	   copy from store
	*/
	GMRFLib_copy_graph(&(opt_problem->sub_graph), store->sub_graph);
    }
    else
    {
	/* 
	   compute it
	*/
	GMRFLib_compute_subgraph(&(opt_problem->sub_graph), graph, fixed_value);

	/* 
	   store it in store if requested
	*/
	if (store_store_sub_graph)
	    GMRFLib_copy_graph(&(store->sub_graph), opt_problem->sub_graph);
    }

    sub_n = opt_problem->sub_graph->n;
    if (sub_n == 0)				  /* fast return if there is nothing todo */
    {
	GMRFLib_free_graph(opt_problem->sub_graph);
	FREE(opt_problem);
	GMRFLib_LEAVE_ROUTINE;
	return GMRFLib_SUCCESS;
    }

    /* 
       the mapping is there in the graph, make a new pointer in the opt_problem-definition
     */
    opt_problem->map = opt_problem->sub_graph->mothergraph_idx;

    /* 
       setup space & misc
     */
    opt_problem->mode = Calloc(sub_n, double); MEMCHK(opt_problem->mode);
    opt_problem->b    = Calloc(sub_n, double); MEMCHK(opt_problem->b);
    opt_problem->d    = Calloc(sub_n, double); MEMCHK(opt_problem->d);

    for(i=0;i<sub_n;i++) opt_problem->mode[i] = mode[opt_problem->map[i]];
    if (b) for(i=0;i<sub_n;i++) opt_problem->b[i] = b[opt_problem->map[i]];
    if (d) for(i=0;i<sub_n;i++) opt_problem->d[i] = d[opt_problem->map[i]];
    
    cc = Calloc(sub_n, double); MEMCHK(cc);
    if (c) for(i=0;i<sub_n;i++) cc[i] = c[opt_problem->map[i]];

    opt_problem->x_vec = Calloc(graph->n, double); MEMCHK(opt_problem->x_vec);
    memcpy(opt_problem->x_vec, mode, graph->n*sizeof(double));
	   
    /* 
       FIXME: i might want to make a wrapper of this one, then REMEMBER TO CHANGE ->map[i] in all
       calls to GMRFLib_2order_approx to i, or what it should be.!!!
     */
    opt_problem->loglFunc     = loglFunc;	  /* i might want to make a wrapper of this one! */
    opt_problem->loglFunc_arg = loglFunc_arg;

    /* 
       make the arguments to the wrapper function
     */
    opt_problem->sub_Qfunc          = GMRFLib_Qfunc_wrapper;
    opt_problem->sub_Qfunc_arg      = Calloc(1, GMRFLib_Qfunc_arg_tp); MEMCHK(opt_problem->sub_Qfunc_arg);
    opt_problem->sub_Qfunc_arg->map = opt_problem->map; /* yes, this ptr is needed */
    opt_problem->sub_Qfunc_arg->diagonal_adds = cc;

    opt_problem->sub_Qfunc_arg->user_Qfunc      = Qfunc;
    opt_problem->sub_Qfunc_arg->user_Qfunc_args = Qfunc_args;
    
    /* 
       now compute the new 'effective' b, and then the mean. recall to add the 'c' term manually,
       since we're using the original Qfunc.
     */
    if (!fixed_value)				  /* then sub_graph = graph and map=I*/
    {
	if (mean)
	{
	    double *tmp = NULL;
	    tmp = Calloc(graph->n, double); MEMCHK(tmp);
	    GMRFLib_Qx(tmp, mean, graph, Qfunc, Qfunc_args);
	    for(i=0;i<graph->n;i++) opt_problem->b[i] += tmp[i] + cc[i]*mean[i];
	    FREE(tmp);
	}
    }
    else
    {
	/* 
	   x=(x1,x2), then x1|x2 has b = Q11 \mu1 - Q12(x2-\mu2)
	 */
	for(i=0;i<sub_n;i++)		  /* loop over all sub_nodes */