Exemple #1
0
// [[Rcpp::export]]
arma::rowvec euler_hat_ds_alt( 
                  arma::rowvec exog, arma::rowvec endog, arma::rowvec cont,
                  arma::mat exog_innov_integ, double betta, 
                  double gamma, arma::mat coeffs_cont, 
                  int n_exog, int n_endog, int n_cont, int n_fwd,
                  arma::rowvec rho, int n_integ, int N, arma::rowvec upper, 
                  arma::rowvec lower, bool cheby, arma::rowvec weights,
                  bool print_rhs=false ){
// Computes the single-period error on the Euler equations
  
//  double betta = params["betta"] ;
//  double gamma = params["gamma"] ;
  double rho_pref = - std::log( betta ) ;
      // Extract coefficients
  double NFA = endog( 0 ) ;
  double z1 = endog( 1 ) ;
  double z2 = endog( 2 ) ;
      // Extract the endogenous states
  double c1 = cont(0) ;
  double c2 = cont(1) ;
  double q = cont(15) ;
  double af1 = cont(16) ;
      // Extract controls
  
  mat exog_lead = zeros( n_integ, n_exog ) ;
      // Initalize the draws of the exogenous variables in the next period
  exog_lead = ones(n_integ) * ( rho % exog ) + exog_innov_integ ;
        // Multiply the most recent exogenous draw by the appropriate rho and
        // add the innovation
  
  rowvec integral = zeros<rowvec>( n_fwd ) ;
  mat integrand = zeros( n_integ, n_fwd ) ;
      // Initialize the right hand side.
      // Add the extra two columns for the extra equations for the prices 
      // r1 and r2
      
  for( int i = 0 ; i < n_integ ; i++ ){
    integrand.row(i) = integrand_ds( endog, exog_lead.row(i), gamma, 
                                      coeffs_cont, n_exog, n_endog, 
                                      n_cont, N, upper, lower, cheby ) ;
  }   // Compute the integral

  integral = weights * integrand ;
  
  if( print_rhs ){
    Rcout << "err: \n" << integrand << std::endl ;
    Rcout << "weights:" << weights << std::endl ;
    Rcout << "integral: " << integral << std::endl ;
    Rcout << "integral(0) - 1 = " << integral(0) - 1 << std::endl ;
    
  }
  
  rowvec out(4) ;
  out(0) = z1  + ( gamma * c1 - rho_pref + std::log( integral(0) ) ) ;
  out(1) = z2  - ( gamma * c1 - rho_pref + std::log( integral(1) ) ) ;
  out(2) = af1 + ( gamma * c2 - rho_pref + std::log( integral(2) ) ) ;
  out(3) = q   + ( gamma * c2 - rho_pref + std::log( integral(3) ) ) ;
      // The predictors.  Set up z1, Z_2 s.t. if current consumption is too high
      // for the Euler equation to hold then z1 decreases.  This will pull down 
      // on consumption in the contemporaneous block later.  Similarly, for af1:
      // if the expected return on asset 2 is too high then the investment share
      // in asset 1 declines.  Finally, if q(+1) is too high
  return out ;
      // Return predictors for (B11, B22, r1, r2)
  
}
bool check(int x, int y)
{
  int z = ( x ^ y );
  return ones(z) == 1;
}
//----------------------------------------------------------------------------
int snl_fei::LinearSystem_General::enforceEssentialBC_LinSysCore()
{
  fei::Matrix* matptr = matrix_.get();
  fei::MatrixReducer* matred = dynamic_cast<fei::MatrixReducer*>(matptr);
  if (matred != NULL) {
    matptr = matred->getTargetMatrix().get();
  }

  fei::Matrix_Impl<LinearSystemCore>* lscmatrix =
    dynamic_cast<fei::Matrix_Impl<LinearSystemCore>*>(matptr);
  if (lscmatrix == 0) {
    return(-1);
  }

  int localsize = matrixGraph_->getRowSpace()->getNumIndices_Owned();
  fei::SharedPtr<fei::Reducer> reducer = matrixGraph_->getReducer();
  if (matrixGraph_->getGlobalNumSlaveConstraints() > 0) {
    localsize = reducer->getLocalReducedEqns().size();
  }

  fei::SharedPtr<fei::FillableMat> inner(new fei::FillableMat);
  bool zeroSharedRows = false;
  fei::SharedPtr<fei::Matrix_Impl<fei::FillableMat> > matrix;
  matrix.reset(new fei::Matrix_Impl<fei::FillableMat>(inner, matrixGraph_, localsize, zeroSharedRows));

  fei::SharedPtr<fei::SparseRowGraph> remoteGraph =
    matrixGraph_->getRemotelyOwnedGraphRows();

  if (!BCenforcement_no_column_mod_) {
    CHK_ERR( snl_fei::gatherRemoteEssBCs(*essBCvalues_, remoteGraph.get(), *matrix) );
  }

  unsigned numBCRows = inner->getNumRows();

  if (output_stream_ != NULL && output_level_ >= fei::BRIEF_LOGS) {
    FEI_OSTREAM& os = *output_stream_;
    os << "#enforceEssentialBC_LinSysCore RemEssBCs to enforce: "
       << numBCRows << FEI_ENDL;
  }

  if (numBCRows > 0 && !BCenforcement_no_column_mod_) {
    std::vector<int*> colIndices(numBCRows);
    std::vector<double*> coefs(numBCRows);
    std::vector<int> colIndLengths(numBCRows);

    fei::CSRMat csrmat(*inner);
    fei::SparseRowGraph& srg = csrmat.getGraph();

    int numEqns = csrmat.getNumRows();
    int* eqns = &(srg.rowNumbers[0]);
    int* rowOffsets = &(srg.rowOffsets[0]);

    for(int i=0; i<numEqns; ++i) {
      colIndices[i] = &(srg.packedColumnIndices[rowOffsets[i]]);
      coefs[i] = &(csrmat.getPackedCoefs()[rowOffsets[i]]);
      colIndLengths[i] = rowOffsets[i+1] - rowOffsets[i];
    }

    int** colInds = &colIndices[0];
    int* colIndLens = &colIndLengths[0];
    double** BCcoefs = &coefs[0];

    if (output_stream_ != NULL && output_level_ > fei::BRIEF_LOGS) {
      FEI_OSTREAM& os = *output_stream_;
      for(int i=0; i<numEqns; ++i) {
        os << "remBCeqn: " << eqns[i] << ", inds/coefs: ";
        for(int j=0; j<colIndLens[i]; ++j) {
          os << "("<<colInds[i][j]<<","<<BCcoefs[i][j]<<") ";
        }
        os << FEI_ENDL;
      }
    }

    int errcode = lscmatrix->getMatrix()->enforceRemoteEssBCs(numEqns,
							      eqns,
							      colInds,
							      colIndLens,
							      BCcoefs);
    if (errcode != 0) {
      return(errcode);
    }
  }

  int numEqns = essBCvalues_->size();
  if (numEqns > 0) {
    int* eqns = &(essBCvalues_->indices())[0];
    double* bccoefs = &(essBCvalues_->coefs())[0];
    std::vector<double> ones(numEqns, 1.0);

    return(lscmatrix->getMatrix()->enforceEssentialBC(eqns, &ones[0],
						    bccoefs, numEqns));
  }

  return(0);
}
Exemple #4
0
  /**
   *  Vertex update function.
   */
  void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext)
  {
    double objective = -0.5*sgd_lambda*latent_factors_inmem[vertex.id()].pvec.squaredNorm();

    // go over all user nodes
    if (vertex.num_outedges() > 1)   // can't compute with CLiMF if we have only 1 out edge!
    {
      vec & U = latent_factors_inmem[vertex.id()].pvec;
      int Ni = vertex.num_edges();

      // precompute f_{ij} = <U_i,V_j> for j = 1..N_i
      std::vector<double> f(Ni);
      int num_relevant = 0;

      for (int j = 0; j < Ni; ++j)
      {
         if (is_relevant(vertex.edge(j)))
         {
           const vec & Vj = latent_factors_inmem[vertex.edge(j)->vertex_id()].pvec;
           f[j] = dot(U, Vj);
           ++num_relevant;
         }
      }

      if (num_relevant < 2)
      {
        return;  // need at least 2 edges to compute updates with CLiMF!
      }

      // compute gradients
      vec dU = -sgd_lambda*U;

      for (int j = 0; j < Ni; ++j)
      {
         if (is_relevant(vertex.edge(j)))
         {
           vec & Vj = latent_factors_inmem[vertex.edge(j)->vertex_id()].pvec;
           vec dVj = g(-f[j])*ones(D) - sgd_lambda*Vj;

           for (int k = 0; k < Ni; ++k)
           {
              if (k != j && is_relevant(vertex.edge(k)))
              {
                 dVj += dg(f[j]-f[k])*(1.0/(1.0-g(f[k]-f[j]))-1.0/(1.0-g(f[j]-f[k])))*U;
              }
           }

           Vj += sgd_gamma*dVj;  // not thread-safe
           dU += g(-f[j])*Vj;

           for (int k = 0; k < Ni; ++k)
           {
              if (k != j && is_relevant(vertex.edge(k)))
              {
                 const vec & Vk = latent_factors_inmem[vertex.edge(k)->vertex_id()].pvec;
                 dU += (Vj-Vk)*dg(f[k]-f[j])/(1.0-g(f[k]-f[j]));
              }
           }
         }
      }

      U += sgd_gamma*dU;  // not thread-safe

      // compute smoothed MRR
      for(int j = 0; j < Ni; j++)
      {
        if (is_relevant(vertex.edge(j)))
        {
          objective += std::log(g(f[j]));
          for(int k = 0; k < Ni; k++)
          {
            if (is_relevant(vertex.edge(k)))
            {
              objective += std::log(1.0-g(f[k]-f[j]));
            }
          }
        }
      }
    }

    assert(objective_vec.size() > omp_get_thread_num());
    objective_vec[omp_get_thread_num()] += objective;
  }
Exemple #5
0
mat<decltype(pow(typename T::value_type(),double(0)))>
pow( const matrix_interface<T>& x, double a )
{
	return pow( x, a*ones( x.size1(),
							  x.size2() ) );
}
Exemple #6
0
mat<decltype(pow(complex(0,0),typename T::value_type()))>
pow( complex a, const matrix_interface<T>& x )
{
	return pow( a*ones( x.size1(),
						x.size2() ), x );
}
Exemple #7
0
vec<decltype(pow(double(0),typename T::value_type()))>
pow( double a, const vector_interface<T>& x )
{
	return pow( a*ones(x.size()), x );
}
/* Add a weak learner h to the strong classifier H */
void addWeak( int posCount, int negCount, int blockCount, int selectTable[],
	float ***POS, float ***NEG, Matrix *posWeight, Matrix *negWeight, Ada *strong, int *hUsed ) {
	/* For all possible features (Bid, Fid) */
	int Iid, Bid, Fid;
	Matrix posCorrect, negCorrect, ONES; /* classification correctness matrices */
	Matrix bestPosCorrect, bestNegCorrect;
	float bestError = 1.f;
	int bestBid, bestFid;
	short bestParity;
	float bestDecision;
	float alpha;
	float normalize;
#if SHOWAVGERROR
	float avgError = 1.f;
	int round = 0;
#endif
	ones( &posCorrect, 1, posCount, 1 );
	ones( &negCorrect, 1, posCount, 1 );
	ones( &ONES, 1, posCount, 1 );

#if 0
	/* Show the data weight */
	full_dump( posWeight, "posWeight", ALL, FLOAT );
	full_dump( negWeight, "negWeight", ALL, FLOAT );
#endif
	
	printf( "Add a weak classifier\n" );
	for ( Bid = 0; Bid < blockCount; Bid++ ) {
		for ( Fid = 0; Fid < FEATURE_COUNT; Fid++ ) {

			float POS_mean = 0.f, NEG_mean = 0.f;
			float decision;
			float error = 0.f;
			short parity = +1; /* default: ... NEG_mean ... | ... POS_mean ... */

			/* [0] Initilize the matrices: Restore to all 1's */
			full_assign( &ONES, &posCorrect, ALL, ALL );
			full_assign( &ONES, &negCorrect, ALL, ALL );

			/* [1] Compute the POS & NEG mean feature value */
			for ( Iid = 0; Iid < posCount; Iid++ ) {
				POS_mean += POS[ Iid ][ Bid ][ Fid ];
				NEG_mean += NEG[ selectTable[ Iid ] ][ Bid ][ Fid ];
			}
			POS_mean /= posCount;
			NEG_mean /= posCount;

			/* default decision threshold: avg of POS_mean and NEG_mean */
			decision = ( POS_mean + NEG_mean ) / 2.f;
			if ( POS_mean < NEG_mean ) {
				parity = -1; /* toggle: ... POS_mean ... | ... NEG_mean ... */
			}
#if 0
			printf( "Bid: %d, Fid: %d, POS_mean: %f, NEG_mean: %f\n", Bid, Fid, POS_mean, NEG_mean );
#endif

			/* [2] Classification and compute the WEIGHTED error rate */
			for ( Iid = 0; Iid < posCount; Iid++ ) {
				/* positive & wrong */
				if ( parity * POS[ Iid ][ Bid ][ Fid ] < parity * decision ) {
					error += posWeight->data[ 0 ][ 0 ][ Iid ];
					posCorrect.data[ 0 ][ 0 ][ Iid ] = -1.f;
				}
				/* negative & wrong */
				if ( parity * NEG[ selectTable[ Iid ] ][ Bid ][ Fid ] > parity * decision ) {
					error += negWeight->data[ 0 ][ 0 ][ Iid ];
					negCorrect.data[ 0 ][ 0 ][ Iid ] = -1.f;
				}
			}
#if SHOWAVGERROR
			printf( "Weighted error rate: %f\n", error );
#endif
			/* record the best h */
			if ( error < bestError ) {
				copy( &posCorrect, &bestPosCorrect );
				copy( &negCorrect, &bestNegCorrect );
				bestError = error;
				bestBid = Bid;
				bestFid = Fid;
				bestParity = parity;
				bestDecision = decision;
			}
#if SHOWAVGERROR
			round++;
			avgError += error;
#endif

		} /* end of loop Fid */
	} /* end of loop Bid */

#if SHOWAVGERROR
	avgError /= round;
	printf( "Avg. weighted error rate: %f\n", avgError );
#endif
	printf( "\nBest weighted error rate: %f, Bid: %d, Fid: %d\n", bestError, bestBid, bestFid );
	/* make sure that best error rate < 0.5 (random guessing) */
	if ( bestError >= 0.5 ) {
		error( "addWeak(): Best error rate is above 0.5!" );
	}
#if 0
	full_dump( &bestPosCorrect, "bestPosCorrect", ALL, INT );
	full_dump( &bestNegCorrect, "bestNegCorrect", ALL, INT );
#endif

	/* [3] Record the best parameters, then determine the alpha weight for this weak classifier. */
	strong[ *hUsed ].Bid = bestBid;
	strong[ *hUsed ].Fid = bestFid;
	strong[ *hUsed ].parity = bestParity;
	strong[ *hUsed ].decision = bestDecision;
	alpha = logf( ( 1.f - bestError ) / bestError ) / 2.f;
	strong[ *hUsed ].alpha = alpha;
	printf( "alpha%d: %f\n", *hUsed, alpha );

	/* [4] Update the data weight */
	s_mul( &bestPosCorrect, -alpha );
	s_mul( &bestNegCorrect, -alpha );
	s_expRaise( &bestPosCorrect );
	s_expRaise( &bestNegCorrect );
	e_mul( &bestPosCorrect, posWeight, posWeight );
	e_mul( &bestNegCorrect, negWeight, negWeight );
	normalize = m_sum( posWeight ) + m_sum( negWeight );
	s_mul( posWeight, 1.f / normalize );
	s_mul( negWeight, 1.f / normalize );

	(*hUsed)++;

	/* free memory space */
	freeMatrix( &posCorrect ); freeMatrix( &negCorrect );
	freeMatrix( &bestPosCorrect ); freeMatrix( &bestNegCorrect );
}
Exemple #9
0
vec<decltype(pow(typename T::value_type(),double(0)))>
pow( const vector_interface<T>& x, double a )
{
	return pow( x, a*ones(x.size()) );
}
Exemple #10
0
vec<decltype(pow(typename T::value_type(),complex(0,0)))>
pow( const vector_interface<T>& x, complex a )
{
	return pow( x, a*ones(x.size()) );
}
//---------------------------------------------------------
void EulerShock2D::precalc_limiter_data()
//---------------------------------------------------------
{

  //---------------------------------------------
  // pre-calculate element geometry and constant 
  // factors for use in this->EulerLimiter2D()
  //---------------------------------------------

  Lim_AVE = 0.5 * MassMatrix.col_sums();
  DMat dropAVE = eye(Np) - outer(ones(Np),Lim_AVE);
  Lim_dx = dropAVE*x; 
  Lim_dy = dropAVE*y;

  // Extract coordinates of vertices of elements
  IVec v1=EToV(All,1);  Lim_xv1=VX(v1); Lim_yv1=VY(v1);
  IVec v2=EToV(All,2);  Lim_xv2=VX(v2); Lim_yv2=VY(v2);
  IVec v3=EToV(All,3);  Lim_xv3=VX(v3); Lim_yv3=VY(v3);  

  const DVec &xv1=Lim_xv1,&xv2=Lim_xv2,&xv3=Lim_xv3;
  const DVec &yv1=Lim_yv1,&yv2=Lim_yv2,&yv3=Lim_yv3;
  DMat &fnx=Lim_fnx, &fny=Lim_fny, &fL=Lim_fL;

  // Compute face unit normals and lengths
  fnx.resize(3,K); fny.resize(3,K);

  // fnx = (3,K) = [yv2-yv1; yv3-yv2; yv1-yv3];
  fnx.set_row(1, yv2-yv1); fnx.set_row(2, yv3-yv2); fnx.set_row(3, yv1-yv3);

  // fny = (3,K) =  -[xv2-xv1;xv3-xv2;xv1-xv3];
//fny.set_row(1, xv2-xv1); fny.set_row(2, xv3-xv2); fny.set_row(3, xv1-xv3);
  fny.set_row(1, xv1-xv2); fny.set_row(2, xv2-xv3); fny.set_row(3, xv3-xv1);

  fL = sqrt(sqr(fnx)+sqr(fny)); fnx.div_element(fL); fny.div_element(fL);

  //-------------------------------------------------------
  // Compute coords of element centers and face weights
  //-------------------------------------------------------

  // Find neighbors in patch
  Lim_E1=EToE(All,1); Lim_E2=EToE(All,2); Lim_E3=EToE(All,3);

  // Compute coordinates of element centers
  xc0=Lim_AVE*x; xc1=xc0(Lim_E1); xc2=xc0(Lim_E2); xc3=xc0(Lim_E3);
  yc0=Lim_AVE*y; yc1=yc0(Lim_E1); yc2=yc0(Lim_E2); yc3=yc0(Lim_E3);

  // Compute weights for face gradients 
  A0=Lim_AVE*J*TWOTHIRD;
  A1=A0+A0(Lim_E1); A2=A0+A0(Lim_E2); A3=A0+A0(Lim_E3);
  A1_A2_A3 = A1+A2+A3;

  // Find boundary faces for each face 
  Lim_id1=find(BCType.get_col(1),'!',0);
  Lim_id2=find(BCType.get_col(2),'!',0);
  Lim_id3=find(BCType.get_col(3),'!',0);

  // Compute location of centers of reflected ghost elements at boundary faces
  if (1) {
    DMat FL1=fL(1,Lim_id1), Fnx1=fnx(1,Lim_id1), Fny1=fny(1,Lim_id1);
    DVec fL1=FL1, fnx1=Fnx1, fny1=Fny1;
    DVec H1   = 2.0*(dd(A0(Lim_id1),fL1));
    xc1(Lim_id1) += 2.0*fnx1.dm(H1);
    yc1(Lim_id1) += 2.0*fny1.dm(H1);

    DMat FL2=fL(2,Lim_id2), Fnx2=fnx(2,Lim_id2), Fny2=fny(2,Lim_id2);
    DVec fL2=FL2, fnx2=Fnx2, fny2=Fny2;
    DVec H2   = 2.0*(dd(A0(Lim_id2),fL2));
    xc2(Lim_id2) += 2.0*fnx2.dm(H2);
    yc2(Lim_id2) += 2.0*fny2.dm(H2);

    DMat FL3=fL(3,Lim_id3), Fnx3=fnx(3,Lim_id3), Fny3=fny(3,Lim_id3);
    DVec fL3=FL3, fnx3=Fnx3, fny3=Fny3;
    DVec H3   = 2.0*(dd(A0(Lim_id3),fL3));
    xc3(Lim_id3) += 2.0*fnx3.dm(H3);
    yc3(Lim_id3) += 2.0*fny3.dm(H3);
  }

  // Find boundary faces
  IVec bct = trans(BCType);
  Lim_idI = find(bct, '=', (int)BC_In);
  Lim_idO = find(bct, '=', (int)BC_Out);
  Lim_idW = find(bct, '=', (int)BC_Wall);
  Lim_idC = find(bct, '=', (int)BC_Cyl);

  Lim_ctx.resize(3,K); Lim_cty.resize(3,K);
  Lim_ctx.set_row(1,xc1); Lim_ctx.set_row(2,xc2); Lim_ctx.set_row(3,xc3);
  Lim_cty.set_row(1,yc1); Lim_cty.set_row(2,yc2); Lim_cty.set_row(3,yc3);

  // load the set of ids
  Lim_ids.resize(6);
  Lim_ids(1)=1;      Lim_ids(2)=Nfp;    Lim_ids(3)=Nfp+1;
  Lim_ids(4)=2*Nfp;  Lim_ids(5)=3*Nfp;  Lim_ids(6)=2*Nfp+1;

  limQ = Q;
}
Exemple #12
0
// Priority for replacement scheme: (-age, depth). Higher is more important.
static inline int prio(Engine_t self, int ix)
{
        struct ttSlot *slot = &self->tt.slots[ix];
        int age = (self->tt.now - slot->date) & ones(ttDateBits);
        return (-age << ttDepthBits) + slot->depth;
}
Matrix NullActivationFunction::applyDerivative(const Matrix& activations) const
{
    return ones(activations.size(), activations.precision());
}
Exemple #14
0
 /** \brief Create a dense matrix or a matrix with specified sparsity with all entries one */
 static MatType ones(int nrow=1, int ncol=1) { return ones(Sparsity::dense(nrow, ncol)); }
Exemple #15
0
vec<decltype(pow(complex(0,0),typename T::value_type()))>
pow( complex a, const vector_interface<T>& x )
{
	return pow( a*ones(x.size()), x );
}
Exemple #16
0
 static MatType ones(const std::pair<int, int>& rc) { return ones(rc.first, rc.second);}
/* learn AdaBoost stage A[i,j] */
void learnA( int posCount, int negCount, int blockCount, int *rejectCount, bool rejected[], 
	float ***POS, float ***NEG, Ada *H, float *F_current, float d_minA, float f_maxA, FILE *fout ) {

	int selectTable[ posCount ]; /* image selection table */
	int imgCount = posCount * 2;
	float initialW = 1.f / (float)imgCount;
	Matrix posWeight, negWeight; /* data weight in AdaBoost */
	int hAllocated = 10;
	int hUsed = 0;
	int Iid, t;
    float f_local = 1.f;
	float threshold = 0.f; /* threshold of the strong classifier A[i,j], should be recorded */
	Matrix posResult, negResult;

	ones( &posWeight, 1, posCount, 1 );
	ones( &negWeight, 1, posCount, 1 );
	H = (Ada *)malloc( hAllocated * sizeof( Ada ) );
	zeros( &posResult, 1, posCount, 1 );
	zeros( &negResult, 1, posCount, 1 );

	/* Initialize the data weight */
	s_mul( &posWeight, initialW );
	s_mul( &negWeight, initialW );
    /* [0] Randomly select NEG examples from the bootstrap set 
	 * Report an error if NEG images are not enough
	 */
	if ( posCount + (*rejectCount) > negCount ) {
		fprintf( fout, "Warning: Not enough NEG images.\n" );
		error( "learnA(): Not enough NEG images." );
	}
    select_neg( posCount, negCount, rejected, selectTable );

    while ( f_local > f_maxA ) {
		int fpCount; /* false positive count */
		float d_local = 0.f;

        /* [1] Add a weak learner h to the strong classifier A[i,j] */
		/* Use realloc() if H is full */
		if ( hUsed == hAllocated ) {
			hAllocated *= 2;
			printf( "call realloc()\n" );
			H = (Ada*)realloc( H, hAllocated * sizeof( Ada ) );
		}
        addWeak( posCount, negCount, blockCount, selectTable, 
			POS, NEG, &posWeight, &negWeight, H, &hUsed );

		threshold = 0.f; /*** Adjust by the threshold ONLY WHEN NECESSARY ***/

		float minPosResult = 0.f; /* minimum value of the positive result */
		int detect = 0; /* detection count */
		fpCount = 0;

		/* [2.1] Use the H(x) so far to trial-classify 
		 * H(x) = sign( sum[alpha_t * h_t(x)] )
		 * Process the POS and NEG together in one loop
		 */
		for ( Iid = 0; Iid < posCount; Iid++ ) {
			float posTemp = 0.f;
			float negTemp = 0.f;
			for ( t = 0; t < hUsed; t++ ) {
				int Bid = H[ t ].Bid;
				int Fid = H[ t ].Fid;
				short parity = H[ t ].parity;
				float decision = H[ t ].decision;
				float alpha = H[ t ].alpha;
				/* determine that positive is positive */
				if ( parity * POS[ Iid ][ Bid ][ Fid ] >= parity * decision ) {
					posTemp += alpha;	
				}
				/* determine that positive is negative */
				else {
					posTemp -= alpha;
				}
				/* determine that negative is positive */
				if ( parity * NEG[ selectTable[ Iid ] ][ Bid ][ Fid ] >= parity * decision ) {
					negTemp += alpha;	
				}
				/* determine that negative is negative */
				else {
					negTemp -= alpha;
				}
			} /* end of loop "t" */
		
			/* Record into posResult or negResult, and collect min( posResult ) */
			posResult.data[ 0 ][ 0 ][ Iid ] = posTemp;
			negResult.data[ 0 ][ 0 ][ Iid ] = negTemp;
			if ( posTemp < minPosResult ) {
				minPosResult = posTemp;
			}

		} /* end of loop "Iid" */

#if 0
		full_dump( &posResult, "posResult", ALL, FLOAT );
		full_dump( &negResult, "negResult", ALL, FLOAT );
#endif

#if 1
		/* count for detections and false positives */
		for ( Iid = 0; Iid < posCount; Iid++ ) {
			if ( posResult.data[ 0 ][ 0 ][ Iid ] >= 0.f ) {
				detect++;
			}
			if ( negResult.data[ 0 ][ 0 ][ Iid ] >= 0.f ) {
				fpCount++;
			}
		}
		d_local = (float)detect / (float)posCount;
		printf( "Before modify threshold:\n  Detection rate: %f ( %d / %d )\n", d_local, detect, posCount );
        /* [3] Calculate f_local of H(x) */
		f_local = (float)fpCount / (float)posCount;
		printf( "  False positive rate: %f ( %d / %d )\n", f_local, fpCount, posCount );
#endif
				
        /* [2.2] Modify the threshold of H(x) to fulfill d_minA 
		 * If min( posResult ) < 0, then let
		 * result = result - min( posResult ) so that all POS data are
		 * determined as positive, i.e., detection rate = 100% 
		 */
		if ( minPosResult < 0.f ) {
			threshold = minPosResult;
			s_add( &posResult, -threshold );
			s_add( &negResult, -threshold );
		}
		printf( "threshold: %f\n", threshold );
#if 0
		full_dump( &posResult, "posResult", ALL, FLOAT );
		full_dump( &negResult, "negResult", ALL, FLOAT );
#endif

		/* count for detections and false positives */
		detect = 0;
		fpCount = 0;
		for ( Iid = 0; Iid < posCount; Iid++ ) {
			if ( posResult.data[ 0 ][ 0 ][ Iid ] >= 0.f ) {
				detect++;
			}
			if ( negResult.data[ 0 ][ 0 ][ Iid ] >= 0.f ) {
				fpCount++;
			}
		}
		d_local = (float)detect / (float)posCount;
		printf( "  After modify threshold:\n  Detection rate: %f ( %d / %d )\n", d_local, detect, posCount );
		//assert( d_local >= d_minA );

        /* [3] Calculate f_local of H(x) */
		f_local = (float)fpCount / (float)posCount;
		printf( "False positive rate: %f ( %d / %d )\n", f_local, fpCount, posCount );

    } /* end of loop "f_local > f_maxA" */

    *F_current *= f_local;
	printf( "\nWeak learners used: %d\n", hUsed );
    printf( "Overall false positive rate: %f\n", *F_current );

	/* [4] Put in the "rejection list" the negative images rejected by H(x) */
	for ( Iid = 0; Iid < posCount; Iid++ ) {
		if ( negResult.data[ 0 ][ 0 ][ Iid ] < 0.f ) {
			rejected[ selectTable[ Iid ] ] = true;
			(*rejectCount)++;
		}
	}
	printf( "Rejected %d negative images in total.\n", *rejectCount );
	getchar();

	/* [5] Output H(x) information to file */
	fprintf( fout, "%d %f\n", hUsed, threshold );
	for ( t = 0; t < hUsed; t++ ) {
		fprintf( fout, "%d %d %d %f %f\n", 
			H[ t ].Bid, H[ t ].Fid, H[ t ].parity, H[ t ].decision, H[ t ].alpha );
	}

	/* Free memory space */
	freeMatrix( &posWeight );
	freeMatrix( &negWeight );
	free( H );
	freeMatrix( &posResult );
	freeMatrix( &negResult );
}