コード例 #1
0
ファイル: cf_put_heston.C プロジェクト: jayhsieh/premia-13
int CFPutHeston(double s, double strike, double t, double ri, double dividi, double sigma0,double ka,double theta,double sigma2,double rhow,double *ptprice, double *ptdelta)
{
  double proba1,proba2,temp;

  K=strike;
  S=s;
  T=t;
  sigma=sigma2;
  v=sigma0;
  teta=theta;
  lambda=0.;
  r=ri;
  divid=dividi;
  rho=rhow;
  k=ka;

  proba1=probabilities(1);
  proba2=probabilities(2);
  
 temp=K*exp(-r*t)*(1.-proba2);
  temp-=s*(1.-proba1)*exp(-divid*t);

   /* Price*/
  *ptprice=temp;
    
  /* Delta */
*ptdelta=-(1.-proba1)*exp(-divid*t);

  return OK;
}
コード例 #2
0
ファイル: svj.c プロジェクト: jayhsieh/premia-13
int calc_price_svj(SVJPARAMS *svj,double *ptprice, double *ptdelta)
{
  double proba,proba1,proba2,price,delta;
 
  K=svj->K;
  S=svj->St0;
  T=svj->T;
  sigma=svj->sigmav;
  V0=svj->V0;
  teta=svj->theta;
  r=svj->r;
  divid=svj->divid;
  rho=svj->rho;
  kappa=svj->kappa;
  lambda0 = svj->lambda;
  m0 = svj->m0;
  v  = svj->v;
  phi=svj->phi;
  heston = svj->heston;
  merton = svj->merton;
 
  if(svj->type_f==1)
    {
      init_log();
      proba1=probabilities(1);
	  
	  
      init_log();
      proba2=probabilities(2);
	 
      price = phi*(S*proba1*exp(-divid*T) - K*exp(-r*T)*proba2);
      delta = phi*(proba1*exp(-divid*T));
    }
  else if(svj->type_f==2)
    {	
      init_log();
      probadelta = 0;
      proba = probabilities2();
	 
      price = 0.5*(1.+phi)*S*exp(-divid*T) + 0.5*(1.-phi)*K*exp(-r*T) - proba*exp(-r*T);
      probadelta = 1;
      proba = probabilities2();
      delta = 0.5*(1.+phi)*exp(-divid*T) - proba*exp(-r*T);
    }
  else
    {
      printf("Erreur dans svj.c : parametre svj->type_f inconnu.\n");
      exit(-1);
    }
  
  
  /* Price*/
  *ptprice=price;

  /* Delta */
  *ptdelta=delta;
  return OK;
}
コード例 #3
0
void SoftmaxRegression<OptimizerType>::Predict(const arma::mat& testData,
                                               arma::Row<size_t>& predictions)
    const
{
  if (testData.n_rows != FeatureSize())
  {
    std::ostringstream oss;
    oss << "SoftmaxRegression::Predict(): test data has " << testData.n_rows
        << " dimensions, but model has " << FeatureSize() << "dimensions";
    throw std::invalid_argument(oss.str());
  }

  // Calculate the probabilities for each test input.
  arma::mat hypothesis, probabilities;
  if (fitIntercept)
  {
    // In order to add the intercept term, we should compute following matrix:
    //     [1; data] = arma::join_cols(ones(1, data.n_cols), data)
    //     hypothesis = arma::exp(parameters * [1; data]).
    //
    // Since the cost of join maybe high due to the copy of original data,
    // split the hypothesis computation to two components.
    hypothesis = arma::exp(
      arma::repmat(parameters.col(0), 1, testData.n_cols) +
      parameters.cols(1, parameters.n_cols - 1) * testData);
  }
  else
  {
    hypothesis = arma::exp(parameters * testData);
  }

  probabilities = hypothesis / arma::repmat(arma::sum(hypothesis, 0),
                                            numClasses, 1);

  // Prepare necessary data.
  predictions.zeros(testData.n_cols);
  double maxProbability = 0;

  // For each test input.
  for (size_t i = 0; i < testData.n_cols; i++)
  {
    // For each class.
    for (size_t j = 0; j < numClasses; j++)
    {
      // If a higher class probability is encountered, change prediction.
      if (probabilities(j, i) > maxProbability)
      {
        maxProbability = probabilities(j, i);
        predictions(i) = j;
      }
    }

    // Set maximum probability to zero for the next input.
    maxProbability = 0;
  }
}
コード例 #4
0
ファイル: eval_helpers.cpp プロジェクト: iamnik13/catboost
static TVector<double> CalcSigmoid(const TVector<double>& approx) {
    TVector<double> probabilities(approx.size());
    for (int i = 0; i < approx.ysize(); ++i) {
        probabilities[i] = 1 / (1 + exp(-approx[i]));
    }
    return probabilities;
}
コード例 #5
0
ファイル: measurement.cpp プロジェクト: narolez571/QuantEmul
std::string Measurement::performOn(QuantumState* state, int subsystem)
{
    if (!_valid) 
	throw std::runtime_error("You cannot perform this measurement because " + _err);
    _checkSpacesDimensionsMatches(state->space(), subsystem);
    
    std::map< std::string, double > probs = probabilities(*state, subsystem);
    
    //srand(time(NULL));
    double r = (double) rand() / RAND_MAX;
    
    int outcomeNum = 0;
    double probSum = probs[_labels[outcomeNum]];
    
    while (r > probSum) 
	probSum += probs[_labels[++outcomeNum]];
    
    // now in outcomeNum we have our outcome index
    // lets perform changing state
    // first, we need to compute square root of operator
    
    MatrixXcd measureMatr = _getMeasurementMatrix(subsystem, outcomeNum, state->space());
    SelfAdjointEigenSolver<MatrixXcd> solver(measureMatr);
    MatrixXcd root = solver.operatorSqrt();
    
    MatrixXcd newMatrix = (root * state->densityMatrix() * root) / probs[_labels[outcomeNum]];
    state->setMatrix(newMatrix);
    
    return _labels[outcomeNum];
}
コード例 #6
0
  /**
   * Return the probability of the given observation.  If the observation is
   * greater than the number of possible observations, then a crash will
   * probably occur -- bounds checking is not performed.
   *
   * @param observation Observation to return the probability of.
   * @return Probability of the given observation.
   */
  double Probability(const arma::vec& observation) const
  {
    // Adding 0.5 helps ensure that we cast the floating point to a size_t
    // correctly.
    const size_t obs = size_t(observation[0] + 0.5);

    // Ensure that the observation is within the bounds.
    if (obs >= probabilities.n_elem)
    {
      Log::Debug << "DiscreteDistribution::Probability(): received observation "
          << obs << "; observation must be in [0, " << probabilities.n_elem
          << "] for this distribution." << std::endl;
    }

    return probabilities(obs);
  }
コード例 #7
0
ファイル: queryupdater.cpp プロジェクト: Artemid/alchemy-2
void LvrQueryUpdater::writeToFile(LogDouble totalWeight)
{
	vector<LogDouble*> values;
	vector<int> keys;
	cumulativeWeight->getAllKeyValuePairs(keys,values);
	vector<LogDouble> probabilities(values.size());
	for(unsigned int i=0;i<values.size();i++)
	{
		LogDouble p = (*values[i])/totalWeight;
		/*if(p.is_zero)
			probabilities[i] = 0;
		else
			probabilities[i] = exp(p.value);
			*/
		probabilities[i] = p;
	}

	vector<string> queryStrings = queryHashTemplate->getAllData();
	LFileUtils::Instance()->updateFile(probabilities,queryStrings);
}
コード例 #8
0
ファイル: apex_balance.cpp プロジェクト: atrantan/hpx
int hpx_main(boost::program_options::variables_map& vm)
{
    // extract command line argument, i.e. fib(N)
    std::uint64_t n = vm["n-value"].as<std::uint64_t>();
    std::uint64_t units = vm["units"].as<std::uint64_t>();
    std::uint64_t blocks = vm["blocks"].as<std::uint64_t>();

    // Keep track of the time required to execute.
    hpx::util::high_resolution_timer t;

    std::vector<hpx::naming::id_type> localities = hpx::find_all_localities();
    std::vector<double> probabilities(localities.size());
    probabilities[0] = 1.0;

    std::cout << "There are " << localities.size() << " localities." << std::endl;
    std::cout << "Units: " << units << " n: " << n << std::endl;

    for(std::uint64_t block = 0; block < blocks; ++block) {
        std::cout << "Block " << block << std::endl;
        std::list<std::uint64_t> work(units, n);
        std::list<hpx::lcos::future<double> > futures;
        for(std::uint64_t & item : work) {
            do_work_action act;
            size_t next = next_locality(probabilities);
            std::cout << "Will issue work to loc " << next << std::endl;
            futures.push_back(hpx::async(act, localities[next], item));
        }
        std::cout << "Issued work for block " << block << std::endl;
        hpx::lcos::wait_all(futures.begin(), futures.end());
        std::cout << "Work done for block " << block << std::endl;
    }


    char const* fmt = "elapsed time: %1% [s]\n";
    std::cout << (boost::format(fmt) % t.elapsed());

    return hpx::finalize(); // Handles HPX shutdown
}
コード例 #9
0
/// Backward computation of the price of a Zero Coupon Bond
static void CapFloor_BackwardIterationLRS1D(TreeLRS1D* Meth, ModelLRS1D* ModelParam, ZCMarketData* ZCMarket, PnlVect* OptionPriceVect1, PnlVect* OptionPriceVect2, int index_last, int index_first)
{
    double sigma, rho, kappa, lambda;

    int i, j, h;
    double delta_y, delta_t, sqrt_delta_t;
    double price_up, price_middle, price_down;
    double y_00, y_ih, r_ih, phi_ihj, phi_next;


    PnlVect* proba_from_ij;

    proba_from_ij = pnl_vect_create(3);


    ///********* Model parameters *********///
    kappa = (ModelParam->Kappa);
    sigma = (ModelParam->Sigma);
    rho = (ModelParam->Rho);
    lambda = (ModelParam->Lambda);

    delta_t = GET(Meth->t, 1) - GET(Meth->t,0);
    y_00 = r_to_y(ModelParam, -log(BondPrice(GET(Meth->t, 1), ZCMarket))/delta_t);

    for(i = index_last-1; i>=index_first; i--)
    {
        pnl_vect_resize(OptionPriceVect1, 6*i-3);  // OptionPriceVect1 := Price of the bond in the tree at time t(i)

        delta_t = GET(Meth->t, i+1) - GET(Meth->t,i);
        sqrt_delta_t = sqrt(delta_t);
        delta_y = lambda * sqrt_delta_t;

        for( h=0; h<=2*i; h++) /// h : numero de la box
        {
            y_ih = y_00 + (i-h) * delta_y;
            r_ih = y_to_r(ModelParam, y_ih);

            for(j=0;j<number_phi_in_box(i, h);j++) /// Boucle sur les  valeurs de phi à (i,h)
            {
                phi_ihj = phi_value(Meth, i, h, j);

                phi_next = phi_ihj * (1-2*kappa*delta_t) + SQR(sigma) * pow(y_to_r(ModelParam, y_ih), (2*rho)) * delta_t;

                price_up     = Interpolation(Meth, i+1, h  , OptionPriceVect2, phi_next);
                price_middle = Interpolation(Meth, i+1, h+1, OptionPriceVect2, phi_next);
                price_down   = Interpolation(Meth, i+1, h+2, OptionPriceVect2, phi_next);

                probabilities(GET(Meth->t,i), y_ih, phi_ihj, lambda, sqrt_delta_t, ModelParam, ZCMarket, proba_from_ij);

                LET(OptionPriceVect1, index_tree(i,h,j)) = exp(-r_ih*delta_t) * (GET(proba_from_ij,0) * price_up + GET(proba_from_ij,1) * price_middle + GET(proba_from_ij,2) * price_down );

            }
        }

        pnl_vect_clone(OptionPriceVect2, OptionPriceVect1); // Copy OptionPriceVect1 in OptionPriceVect2

    } // END of the loop on i (time)

    pnl_vect_free(&proba_from_ij);

}
コード例 #10
0
static double tr_lrs1d_capfloor(TreeLRS1D* Meth, ModelLRS1D* ModelParam, ZCMarketData* ZCMarket, int NumberOfTimeStep, NumFunc_1 *p, double s, double r, double periodicity,double first_reset_date,double contract_maturity, double CapFloorFixedRate)
{
    double lambda;

    double delta_y; // delta_x1 = space step of the process x at time i ; delta_x2 same at time i+1.
    double delta_t, sqrt_delta_t; // time step

    double OptionPrice, OptionPrice1, OptionPrice2;
    int i, i_s, h_r;
    double theta;
    double y_r, y_ih, y_00, r_00;

    double Ti2, Ti1;
    int i_Ti2, i_Ti1, n;

    PnlVect* proba_from_ih;
    PnlVect* OptionPriceVect1; // Matrix of prices of the option at i
    PnlVect* OptionPriceVect2; // Matrix of prices of the option at i+1

    proba_from_ih = pnl_vect_create(3);
    OptionPriceVect1 = pnl_vect_create(1);
    OptionPriceVect2 = pnl_vect_create(1);

    ///********* Model parameters *********///
    lambda = (ModelParam->Lambda);

    ///**************** PAYOFF at the MATURITY of the OPTION : T(n-1)****************///
    Ti2 = contract_maturity;
    Ti1 = Ti2 - periodicity;

    CapFloor_InitialPayoffLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect2, p, Ti1, Ti2, CapFloorFixedRate);


    ///**************** Backward computation of the option price ****************///
    n = (int) ((contract_maturity-first_reset_date)/periodicity + 0.1);

    if(n>1)
    {
        for(i = n-2; i>=0; i--)
        {
            Ti1 = first_reset_date + i * periodicity;
            Ti2 = Ti1 + periodicity;
            i_Ti2 = indiceTimeLRS1D(Meth, Ti2);
            i_Ti1 = indiceTimeLRS1D(Meth, Ti1);

            CapFloor_BackwardIterationLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, i_Ti2, i_Ti1);

            CapFloor_InitialPayoffLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, p, Ti1, Ti2, CapFloorFixedRate);

            pnl_vect_plus_vect(OptionPriceVect2, OptionPriceVect1);
        }
    }

    ///****************** Price of the option at initial time s *******************///
    i_s = indiceTimeLRS1D(Meth, s); // Localisation of s on the tree

    delta_t = GET(Meth->t, 1) - GET(Meth->t,0);
    sqrt_delta_t = sqrt(delta_t);

    r_00 = -log(BondPrice(GET(Meth->t, 1), ZCMarket))/delta_t;
    y_00 = r_to_y(ModelParam, r_00);

    Ti1 = first_reset_date;
    i_Ti1 = indiceTimeLRS1D(Meth, Ti1);

    if(i_s==0) // If s=0
    {
        CapFloor_BackwardIterationLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, i_Ti1, 1);

        probabilities(GET(Meth->t,0), y_00, 0, lambda, sqrt_delta_t, ModelParam, ZCMarket, proba_from_ih);

        OptionPrice = exp(-r_00*delta_t) * ( GET(proba_from_ih,0) * GET(OptionPriceVect1, 0) + GET(proba_from_ih,1) * GET(OptionPriceVect1,1) + GET(proba_from_ih,2) * GET(OptionPriceVect1, 2));
    }

    else
    {   // We compute the price of the option as a linear interpolation of the prices at the nodes r(i_s,j_r) and r(i_s,j_r+1)

        delta_t = GET(Meth->t, i_s+1) - GET(Meth->t,i_s);
        sqrt_delta_t = sqrt(delta_t);
        delta_y = lambda * sqrt_delta_t;

        y_r = r_to_y(ModelParam, r);

        h_r = (int) floor(i_s - (y_r-y_00)/delta_y); // y_r between y(h_r) et y(h_r+1) : y(h_r+1) < y_r <= y(h_r)

        y_ih = y_00 + (i_s-h_r) * delta_y;

        if(h_r < 0 || h_r > 2*i_s)
        {
          printf("WARNING : Instantaneous futur spot rate is out of tree\n");
          exit(EXIT_FAILURE);
        }

        CapFloor_BackwardIterationLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, i_Ti1, i_s);

        theta = (y_ih - y_r)/delta_y;

        OptionPrice1 = MeanPrice(Meth, i_s, h_r, OptionPriceVect2); //Interpolation(Meth, i_s, h_r  , OptionPriceVect2, phi0);

        OptionPrice2 = MeanPrice(Meth, i_s, h_r+1, OptionPriceVect2); // Interpolation(Meth, i_s, h_r+1  , OptionPriceVect2, phi0);

        OptionPrice = (1-theta) * OptionPrice1 + theta * OptionPrice2 ;
    }

    pnl_vect_free(& OptionPriceVect1);
    pnl_vect_free(& OptionPriceVect2);
    pnl_vect_free(&proba_from_ih);

    return OptionPrice;

}
コード例 #11
0
ファイル: cpu_top.cpp プロジェクト: dgschwend/zynqnet
int main() {
  LOG_LEVEL = 0;

  // ==============
  // = Unit Tests =
  // ==============
  if (!do_unittests()) {
    printf("UNIT TESTS FAILED, ABORTING.");
    return -1;
  };

  // =================
  // = Setup Network =
  // =================
  // Generate + Load Network Config from network.hpp/network.cpp
  network_t *net_CPU;
  net_CPU = get_network_config();

  // Assert that layer_t fits into a multiple of bus transactions:
  // ONLY NECESSARY IF WE CAN MAP LAYER_T TRANSFER ONTO BUS_T AXI MASTER
  // printf("size of layer_t: %d, size of bus_t: %d", (int)sizeof(layer_t),
  //       (int)sizeof(bus_t));
  // assert((sizeof(layer_t) % sizeof(bus_t) == 0) &&
  //       "layert_t is not multiple of bus size. adjust size of
  //       layer_t.dummy!");

  // ==========================
  // = Setup FPGA Accelerator =
  // ==========================
  // Allocate Shared Memory for Config, Weights, Data.
  // Copy Layer Config + Weights to FPGA.
  setup_FPGA(net_CPU);

  // ===========================
  // = Load + Copy Input Image =
  // ===========================
  /* Structured: generate_structured_input_image(input_image,win,hin,chin);
   PseudoRandom: generate_random_input_image(input_image, win, hin, chin, 1);
   ReallyRandom: generate_random_input_image(input_image, win, hin, chin -1);
   Prepared Input File (convert_image.py):
   load_prepared_input_image(input_image, "./indata.bin", win, hin, chin);
   JPG/PNG Input File (!not implemented!):
   load_image_file(input_image, "./puppy-500x350.jpg", win, hin, chin);
   do_preprocess(input_image, win, hin, chin); */

  // Allocate Memory on CPU Side:
  layer_t layer0 = net_CPU->layers[0];
  int win = layer0.width;
  int hin = layer0.height;
  int chin = layer0.channels_in;
  data_t *input_image = (data_t *)malloc(win * hin * chin * sizeof(data_t));

  // Load Input Image
  load_prepared_input_image(input_image, "./indata.bin", win, hin, chin);

  // Copy onto FPGA
  copy_input_image_to_FPGA(net_CPU, input_image);

// ============================
// = Execute FPGA Accelerator =
// ============================

L_LAYERS:
  for (int layer_id = 0; layer_id < net_CPU->num_layers; layer_id++) {
    layer_t layer = net_CPU->layers[layer_id];
    LOG("Layer %2d: <%s>\n", layer_id, layer.name);
    LOG_LEVEL_INCR;

    // Calculate Memory Pointers
    LOG("SHARED_DRAM is at address: %lu\n", (long)SHARED_DRAM);
    int weights_offset =
        ((long)SHARED_DRAM_WEIGHTS - (long)SHARED_DRAM) / sizeof(data_t);
    int input_offset =
        ((long)SHARED_DRAM_DATA - (long)SHARED_DRAM) / sizeof(data_t);
    numfilterelems_t weights_per_filter = (layer.kernel == 3) ? 9 : 1;
    weightaddr_t num_weights =
        layer.channels_in * layer.channels_out * weights_per_filter;

    // Print some Info on this Layer
    printf("CPU: Offload CONV Layer ");
    print_layer(&layer);
    fflush(stdout);

    // Offload Layer Calculation to FPGA
    fpga_top(layer, (data_t *)SHARED_DRAM, weights_offset, num_weights,
             input_offset);

    LOG_LEVEL_DECR;
  }

  LOG_LEVEL = 0;

  // ===============================
  // = Copy Results back from FPGA =
  // ===============================
  layer_t *final = &net_CPU->layers[net_CPU->num_layers - 1];
  int ch_out = (final->is_second_split_layer ? 2 : 1) * final->channels_out;
  
  data_t *results = (data_t *)malloc(ch_out * sizeof(data_t));
  copy_results_from_FPGA(net_CPU, results, ch_out);

  // =====================
  // = Calculate Softmax =
  // =====================
  std::vector<std::pair<data_t, int> > probabilities(ch_out);
  calculate_softmax(net_CPU, results, probabilities);

  // ==================
  // = Report Results =
  // ==================
  printf("\nResult (top-5):\n====================\n");
  for (int i = 0; i < std::min(5, ch_out); i++) {
    printf("    %5.2f%%: class %3d (output %6.2f)\n",
           100 * probabilities[i].first, probabilities[i].second,
           results[probabilities[i].second]);
  }

  // ====================
  // = TestBench Result =
  // ====================
  // Check if output is AS EXPECTED (+- 0.5%) (defined in network.hpp)
  if (fabs(100 * probabilities[0].first - TEST_RESULT_EXPECTED) < 0.1) {
    printf("\nTestBench Result: SUCCESS\n");
    return 0;
  } else {
    printf("\nTestBench Result: FAILURE\n");
    printf("Actual: %5.2f, Expected: %5.2f\n", 100 * probabilities[0].first,
           TEST_RESULT_EXPECTED);
    return -1;
  }
}
コード例 #12
0
ファイル: predict.cpp プロジェクト: NikolausDemmel/curfil
void test(RandomForestImage& randomForest, const std::string& folderTesting,
        const std::string& folderPrediction, const bool useDepthFilling,
        const bool writeProbabilityImages) {

    auto filenames = listImageFilenames(folderTesting);
    if (filenames.empty()) {
        throw std::runtime_error(std::string("found no files in ") + folderTesting);
    }

    CURFIL_INFO("got " << filenames.size() << " files for prediction");

    CURFIL_INFO("label/color map:");
    const auto labelColorMap = randomForest.getLabelColorMap();
    for (const auto& labelColor : labelColorMap) {
        const auto color = LabelImage::decodeLabel(labelColor.first);
        CURFIL_INFO("label: " << static_cast<int>(labelColor.first) << ", color: RGB(" << color << ")");
    }

    tbb::mutex totalMutex;
    utils::Average averageAccuracy;
    utils::Average averageAccuracyWithoutVoid;

    const LabelType numClasses = randomForest.getNumClasses();
    ConfusionMatrix totalConfusionMatrix(numClasses);

    size_t i = 0;

    const bool useCIELab = randomForest.getConfiguration().isUseCIELab();
    CURFIL_INFO("CIELab: " << useCIELab);
    CURFIL_INFO("DepthFilling: " << useDepthFilling);

    bool onGPU = randomForest.getConfiguration().getAccelerationMode() == GPU_ONLY;

    size_t grainSize = 1;
    if (!onGPU) {
        grainSize = filenames.size();
    }

    bool writeImages = true;
    if (folderPrediction.empty()) {
        CURFIL_WARNING("no prediction folder given. will not write images");
        writeImages = false;
    }

    tbb::parallel_for(tbb::blocked_range<size_t>(0, filenames.size(), grainSize),
            [&](const tbb::blocked_range<size_t>& range) {
                for(size_t fileNr = range.begin(); fileNr != range.end(); fileNr++) {
                    const std::string& filename = filenames[fileNr];
                    const auto imageLabelPair = loadImagePair(filename, useCIELab, useDepthFilling);
                    const RGBDImage& testImage = imageLabelPair.getRGBDImage();
                    const LabelImage& groundTruth = imageLabelPair.getLabelImage();
                    LabelImage prediction(testImage.getWidth(), testImage.getHeight());

                    for(int y = 0; y < groundTruth.getHeight(); y++) {
                        for(int x = 0; x < groundTruth.getWidth(); x++) {
                            const LabelType label = groundTruth.getLabel(x, y);
                            if (label >= numClasses) {
                                const auto msg = (boost::format("illegal label in ground truth image '%s' at pixel (%d,%d): %d RGB(%3d,%3d,%3d) (numClasses: %d)")
                                        % filename
                                        % x % y
                                        % static_cast<int>(label)
                                        % LabelImage::decodeLabel(label)[0]
                                        % LabelImage::decodeLabel(label)[1]
                                        % LabelImage::decodeLabel(label)[2]
                                        % static_cast<int>(numClasses)
                                ).str();
                                throw std::runtime_error(msg);
                            }
                        }
                    }

                    boost::filesystem::path fn(testImage.getFilename());
                    const std::string basepath = folderPrediction + "/" + boost::filesystem::basename(fn);

                    cuv::ndarray<float, cuv::host_memory_space> probabilities;

                    prediction = randomForest.predict(testImage, &probabilities, onGPU);

#ifndef NDEBUG
            for(LabelType label = 0; label < randomForest.getNumClasses(); label++) {
                if (!randomForest.shouldIgnoreLabel(label)) {
                    continue;
                }

                // ignored classes must not be predicted as we did not sample them
                for(size_t y = 0; y < probabilities.shape(0); y++) {
                    for(size_t x = 0; x < probabilities.shape(1); x++) {
                        const float& probability = probabilities(label, y, x);
                        assert(probability == 0.0);
                    }
                }
            }
#endif

            if (writeImages && writeProbabilityImages) {
                utils::Profile profile("writeProbabilityImages");
                RGBDImage probabilityImage(testImage.getWidth(), testImage.getHeight());
                for(LabelType label = 0; label< randomForest.getNumClasses(); label++) {

                    if (randomForest.shouldIgnoreLabel(label)) {
                        continue;
                    }

                    for(int y = 0; y < probabilityImage.getHeight(); y++) {
                        for(int x = 0; x < probabilityImage.getWidth(); x++) {
                            const float& probability = probabilities(label, y, x);
                            for(int c=0; c<3; c++) {
                                probabilityImage.setColor(x, y, c, probability);
                            }
                        }
                    }
                    const std::string filename = (boost::format("%s_label_%d.png") % basepath % static_cast<int>(label)).str();
                    probabilityImage.saveColor(filename);
                }
            }

            int thisNumber;

            {
                tbb::mutex::scoped_lock total(totalMutex);
                thisNumber = i++;
            }

            if (writeImages) {
                utils::Profile profile("writeImages");
                testImage.saveColor(basepath + ".png");
                testImage.saveDepth(basepath + "_depth.png");
                groundTruth.save(basepath + "_ground_truth.png");
                prediction.save(basepath + "_prediction.png");
            }

            ConfusionMatrix confusionMatrix(numClasses);
            double accuracy = calculatePixelAccuracy(prediction, groundTruth, true, &confusionMatrix);
            double accuracyWithoutVoid = calculatePixelAccuracy(prediction, groundTruth, false);

            tbb::mutex::scoped_lock lock(totalMutex);

            CURFIL_INFO("prediction " << (thisNumber + 1) << "/" << filenames.size()
                    << " (" << testImage.getFilename() << "): pixel accuracy (without void): " << 100 * accuracy
                    << " (" << 100 * accuracyWithoutVoid << ")");

            averageAccuracy.addValue(accuracy);
            averageAccuracyWithoutVoid.addValue(accuracyWithoutVoid);

            totalConfusionMatrix += confusionMatrix;
        }

    });

    tbb::mutex::scoped_lock lock(totalMutex);
    double accuracy = averageAccuracy.getAverage();
    double accuracyWithoutVoid = averageAccuracyWithoutVoid.getAverage();

    totalConfusionMatrix.normalize();

    CURFIL_INFO(totalConfusionMatrix);

    CURFIL_INFO("pixel accuracy: " << 100 * accuracy);
    CURFIL_INFO("pixel accuracy without void: " << 100 * accuracyWithoutVoid);
}
コード例 #13
0
ファイル: simulation.cpp プロジェクト: canercandan/dim
int main (int argc, char *argv[])
{
    /*************************
     * Initialisation de MPI *
     *************************/

    boost::mpi::environment env(argc, argv, MPI_THREAD_MULTIPLE, true);
    boost::mpi::communicator world;

    /****************************
     * Il faut au moins 4 nœuds *
     ****************************/

    const size_t ALL = world.size();
    const size_t RANK = world.rank();

    /************************
     * Initialisation de EO *
     ************************/

    eoParser parser(argc, argv);
    eoState state;    // keeps all things allocated
    dim::core::State state_dim;    // keeps all things allocated

    /*****************************
     * Definition des paramètres *
     *****************************/

    bool sync = parser.createParam(bool(true), "sync", "sync", 0, "Islands Model").value();
    bool smp = parser.createParam(bool(true), "smp", "smp", 0, "Islands Model").value();
    unsigned nislands = parser.createParam(unsigned(4), "nislands", "Number of islands (see --smp)", 0, "Islands Model").value();
    // a
    double alphaP = parser.createParam(double(0.2), "alpha", "Alpha Probability", 'a', "Islands Model").value();
    double alphaF = parser.createParam(double(0.01), "alphaF", "Alpha Fitness", 'A', "Islands Model").value();
    // b
    double betaP = parser.createParam(double(0.01), "beta", "Beta Probability", 'b', "Islands Model").value();
    // d
    double probaSame = parser.createParam(double(100./(smp ? nislands : ALL)), "probaSame", "Probability for an individual to stay in the same island", 'd', "Islands Model").value();
    // I
    bool initG = parser.createParam(bool(true), "initG", "initG", 'I', "Islands Model").value();

    bool update = parser.createParam(bool(true), "update", "update", 'U', "Islands Model").value();
    bool feedback = parser.createParam(bool(true), "feedback", "feedback", 'F', "Islands Model").value();
    bool migrate = parser.createParam(bool(true), "migrate", "migrate", 'M', "Islands Model").value();
    unsigned nmigrations = parser.createParam(unsigned(1), "nmigrations", "Number of migrations to do at each generation (0=all individuals are migrated)", 0, "Islands Model").value();
    unsigned stepTimer = parser.createParam(unsigned(1000), "stepTimer", "stepTimer", 0, "Islands Model").value();
    bool deltaUpdate = parser.createParam(bool(true), "deltaUpdate", "deltaUpdate", 0, "Islands Model").value();
    bool deltaFeedback = parser.createParam(bool(true), "deltaFeedback", "deltaFeedback", 0, "Islands Model").value();
    double sensitivity = 1 / parser.createParam(double(1.), "sensitivity", "sensitivity of delta{t} (1/sensitivity)", 0, "Islands Model").value();
    std::string rewardStrategy = parser.createParam(std::string("avg"), "rewardStrategy", "Strategy of rewarding: best or avg", 0, "Islands Model").value();

    std::vector<double> rewards(smp ? nislands : ALL, 1.);
    std::vector<double> timeouts(smp ? nislands : ALL, 1.);

    for (size_t i = 0; i < (smp ? nislands : ALL); ++i)
    {
        std::ostringstream ss;
        ss << "reward" << i;
        rewards[i] = parser.createParam(double(1.), ss.str(), ss.str(), 0, "Islands Model").value();
        ss.str("");
        ss << "timeout" << i;
        timeouts[i] = parser.createParam(double(1.), ss.str(), ss.str(), 0, "Islands Model").value();
    }

    /*********************************
     * Déclaration des composants EO *
     *********************************/

    unsigned chromSize = parser.getORcreateParam(unsigned(0), "chromSize", "The length of the bitstrings", 'n',"Problem").value();
    eoInit<EOT>& init = dim::do_make::genotype(parser, state, EOT(), 0);

    eoEvalFunc<EOT>* ptEval = NULL;
    ptEval = new SimulatedEval( rewards[RANK] );
    state.storeFunctor(ptEval);

    eoEvalFuncCounter<EOT> eval(*ptEval);

    unsigned popSize = parser.getORcreateParam(unsigned(100), "popSize", "Population Size", 'P', "Evolution Engine").value();
    dim::core::Pop<EOT>& pop = dim::do_make::detail::pop(parser, state, init);

    double targetFitness = parser.getORcreateParam(double(1000), "targetFitness", "Stop when fitness reaches",'T', "Stopping criterion").value();
    unsigned maxGen = parser.getORcreateParam(unsigned(0), "maxGen", "Maximum number of generations () = none)",'G',"Stopping criterion").value();
    dim::continuator::Base<EOT>& continuator = dim::do_make::continuator<EOT>(parser, state, eval);

    dim::core::IslandData<EOT> data(smp ? nislands : -1);

    std::string monitorPrefix = parser.getORcreateParam(std::string("result"), "monitorPrefix", "Monitor prefix filenames", '\0', "Output").value();
    dim::utils::CheckPoint<EOT>& checkpoint = dim::do_make::checkpoint<EOT>(parser, state, continuator, data, 1, stepTimer);

    /**************
     * EO routine *
     **************/

    make_parallel(parser);
    make_verbose(parser);
    make_help(parser);

    if (!smp) // no smp enabled use mpi instead
    {

        /****************************************
         * Distribution des opérateurs aux iles *
         ****************************************/

        eoMonOp<EOT>* ptMon = NULL;
        if (sync)
        {
            ptMon = new DummyOp;
        }
        else
        {
            ptMon = new SimulatedOp( timeouts[RANK] );
        }
        state.storeFunctor(ptMon);

        /**********************************
         * Déclaration des composants DIM *
         **********************************/

        dim::core::ThreadsRunner< EOT > tr;

        dim::evolver::Easy<EOT> evolver( /*eval*/*ptEval, *ptMon, false );

        dim::feedbacker::Base<EOT>* ptFeedbacker = NULL;
        if (feedback)
        {
            if (sync)
            {
                ptFeedbacker = new dim::feedbacker::sync::Easy<EOT>(alphaF);
            }
            else
            {
                ptFeedbacker = new dim::feedbacker::async::Easy<EOT>(alphaF, sensitivity, deltaFeedback);
            }
        }
        else
        {
            ptFeedbacker = new dim::algo::Easy<EOT>::DummyFeedbacker();
        }
        state_dim.storeFunctor(ptFeedbacker);

        dim::vectorupdater::Base<EOT>* ptUpdater = NULL;
        if (update)
        {
            dim::vectorupdater::Reward<EOT>* ptReward = NULL;
            if (rewardStrategy == "best")
            {
                ptReward = new dim::vectorupdater::Best<EOT>(alphaP, betaP);
            }
            else
            {
                ptReward = new dim::vectorupdater::Average<EOT>(alphaP, betaP, sensitivity, sync ? false : deltaUpdate);
            }
            state_dim.storeFunctor(ptReward);

            ptUpdater = new dim::vectorupdater::Easy<EOT>(*ptReward);
        }
        else
        {
            ptUpdater = new dim::algo::Easy<EOT>::DummyVectorUpdater();
        }
        state_dim.storeFunctor(ptUpdater);

        dim::memorizer::Easy<EOT> memorizer;

        dim::migrator::Base<EOT>* ptMigrator = NULL;
        if (migrate)
        {
            if (sync)
            {
                ptMigrator = new dim::migrator::sync::Easy<EOT>();
            }
            else
            {
                ptMigrator = new dim::migrator::async::Easy<EOT>(nmigrations);
            }
        }
        else
        {
            ptMigrator = new dim::algo::Easy<EOT>::DummyMigrator();
        }
        state_dim.storeFunctor(ptMigrator);

        dim::algo::Easy<EOT> island( evolver, *ptFeedbacker, *ptUpdater, memorizer, *ptMigrator, checkpoint, monitorPrefix );

        if (!sync)
        {
            tr.addHandler(*ptFeedbacker).addHandler(*ptMigrator).add(island);
        }

        /***************
         * Rock & Roll *
         ***************/

        /******************************************************************************
         * Création de la matrice de transition et distribution aux iles des vecteurs *
         ******************************************************************************/

        dim::core::MigrationMatrix probabilities( ALL );
        dim::core::InitMatrix initmatrix( initG, probaSame );

        if ( 0 == RANK )
        {
            initmatrix( probabilities );
            std::cout << probabilities;
            data.proba = probabilities(RANK);

            for (size_t i = 1; i < ALL; ++i)
            {
                world.send( i, 100, probabilities(i) );
            }

            std::cout << "Island Model Parameters:" << std::endl
                      << "alphaP: " << alphaP << std::endl
                      << "alphaF: " << alphaF << std::endl
                      << "betaP: " << betaP << std::endl
                      << "probaSame: " << probaSame << std::endl
                      << "initG: " << initG << std::endl
                      << "update: " << update << std::endl
                      << "feedback: " << feedback << std::endl
                      << "migrate: " << migrate << std::endl
                      << "sync: " << sync << std::endl
                      << "stepTimer: " << stepTimer << std::endl
                      << "deltaUpdate: " << deltaUpdate << std::endl
                      << "deltaFeedback: " << deltaFeedback << std::endl
                      << "sensitivity: " << sensitivity << std::endl
                      << "chromSize: " << chromSize << std::endl
                      << "popSize: " << popSize << std::endl
                      << "targetFitness: " << targetFitness << std::endl
                      << "maxGen: " << maxGen << std::endl
                      ;
        }
        else
        {
            world.recv( 0, 100, data.proba );
        }

        /******************************************
         * Get the population size of all islands *
         ******************************************/

        world.barrier();
        dim::utils::print_sum(pop);

        FitnessInit fitInit;

        apply<EOT>(fitInit, pop);

        if (sync)
        {
            island( pop, data );
        }
        else
        {
            tr( pop, data );
        }

        world.abort(0);

        return 0 ;

    }

    // smp

    /**********************************
     * Déclaration des composants DIM *
     **********************************/

    dim::core::ThreadsRunner< EOT > tr;

    std::vector< dim::core::Pop<EOT> > islandPop(nislands);
    std::vector< dim::core::IslandData<EOT> > islandData(nislands);

    dim::core::MigrationMatrix probabilities( nislands );
    dim::core::InitMatrix initmatrix( initG, probaSame );

    initmatrix( probabilities );
    std::cout << probabilities;

    FitnessInit fitInit;

    for (size_t i = 0; i < nislands; ++i)
    {
        std::cout << "island " << i << std::endl;

        islandPop[i].append(popSize, init);

        apply<EOT>(fitInit, islandPop[i]);

        islandData[i] = dim::core::IslandData<EOT>(nislands, i);

        std::cout << islandData[i].size() << " " << islandData[i].rank() << std::endl;

        islandData[i].proba = probabilities(i);
        apply<EOT>(eval, islandPop[i]);

        /****************************************
         * Distribution des opérateurs aux iles *
         ****************************************/

        eoMonOp<EOT>* ptMon = NULL;
        ptMon = new SimulatedOp( timeouts[islandData[i].rank()] );
        state.storeFunctor(ptMon);

        eoEvalFunc<EOT>* __ptEval = NULL;
        __ptEval = new SimulatedEval( rewards[islandData[i].rank()] );
        state.storeFunctor(__ptEval);

        dim::evolver::Base<EOT>* ptEvolver = new dim::evolver::Easy<EOT>( /*eval*/*__ptEval, *ptMon, false );
        state_dim.storeFunctor(ptEvolver);

        dim::feedbacker::Base<EOT>* ptFeedbacker = new dim::feedbacker::smp::Easy<EOT>(islandPop, islandData, alphaF);
        state_dim.storeFunctor(ptFeedbacker);

        dim::vectorupdater::Reward<EOT>* ptReward = NULL;
        if (rewardStrategy == "best")
        {
            ptReward = new dim::vectorupdater::Best<EOT>(alphaP, betaP);
        }
        else
        {
            ptReward = new dim::vectorupdater::Average<EOT>(alphaP, betaP, sensitivity, sync ? false : deltaUpdate);
        }
        state_dim.storeFunctor(ptReward);

        dim::vectorupdater::Base<EOT>* ptUpdater = new dim::vectorupdater::Easy<EOT>(*ptReward);
        state_dim.storeFunctor(ptUpdater);

        dim::memorizer::Base<EOT>* ptMemorizer = new dim::memorizer::Easy<EOT>();
        state_dim.storeFunctor(ptMemorizer);

        dim::migrator::Base<EOT>* ptMigrator = new dim::migrator::smp::Easy<EOT>(islandPop, islandData, monitorPrefix);
        state_dim.storeFunctor(ptMigrator);

        dim::utils::CheckPoint<EOT>& checkpoint = dim::do_make::checkpoint<EOT>(parser, state, continuator, islandData[i], 1, stepTimer);

        dim::algo::Base<EOT>* ptIsland = new dim::algo::smp::Easy<EOT>( *ptEvolver, *ptFeedbacker, *ptUpdater, *ptMemorizer, *ptMigrator, checkpoint, islandPop, islandData, monitorPrefix );
        state_dim.storeFunctor(ptIsland);

        ptEvolver->size(nislands);
        ptFeedbacker->size(nislands);
        ptReward->size(nislands);
        ptUpdater->size(nislands);
        ptMemorizer->size(nislands);
        ptMigrator->size(nislands);
        ptIsland->size(nislands);

        ptEvolver->rank(i);
        ptFeedbacker->rank(i);
        ptReward->rank(i);
        ptUpdater->rank(i);
        ptMemorizer->rank(i);
        ptMigrator->rank(i);
        ptIsland->rank(i);

        tr.add(*ptIsland);
    }

    tr(pop, data);

    return 0 ;
}
コード例 #14
0
ファイル: cosine_tree.cpp プロジェクト: AmesianX/mlpack
double CosineTree::MonteCarloError(CosineTree* node,
                                   CosineNodeQueue& treeQueue,
                                   arma::vec* addBasisVector1,
                                   arma::vec* addBasisVector2)
{
  std::vector<size_t> sampledIndices;
  arma::vec probabilities;

  // Sample O(log m) points from the input node's distribution.
  // 'm' is the number of columns present in the node.
  size_t numSamples = log(node->NumColumns()) + 1;
  node->ColumnSamplesLS(sampledIndices, probabilities, numSamples);

  // Get pointer to the original dataset.
  arma::mat dataset = node->GetDataset();

  // Initialize weighted projection magnitudes as zeros.
  arma::vec weightedMagnitudes;
  weightedMagnitudes.zeros(numSamples);

  // Set size of projection vector, depending on whether additional basis
  // vectors are passed.
  size_t projectionSize;
  if (addBasisVector1 && addBasisVector2)
    projectionSize = treeQueue.size() + 2;
  else
    projectionSize = treeQueue.size();

  // For each sample, calculate the weighted projection onto the current basis.
  for (size_t i = 0; i < numSamples; i++)
  {
    // Initialize projection as a vector of zeros.
    arma::vec projection;
    projection.zeros(projectionSize);

    CosineTree *currentNode;
    CosineNodeQueue::const_iterator j = treeQueue.begin();

    size_t k = 0;
    // Compute the projection of the sampled vector onto the existing subspace.
    for ( ; j != treeQueue.end(); j++, k++)
    {
      currentNode = *j;

      projection(k) = arma::dot(dataset.col(sampledIndices[i]),
                                currentNode->BasisVector());
    }
    // If two additional vectors are passed, take their projections.
    if (addBasisVector1 && addBasisVector2)
    {
      projection(k++) = arma::dot(dataset.col(sampledIndices[i]),
                                  *addBasisVector1);
      projection(k) = arma::dot(dataset.col(sampledIndices[i]),
                                *addBasisVector2);
    }

    // Calculate the Frobenius norm squared of the projected vector.
    double frobProjection = arma::norm(projection, "frob");
    double frobProjectionSquared = frobProjection * frobProjection;

    // Calculate the weighted projection magnitude.
    weightedMagnitudes(i) = frobProjectionSquared / probabilities(i);
  }

  // Compute mean and standard deviation of the weighted samples.
  double mu = arma::mean(weightedMagnitudes);
  double sigma = arma::stddev(weightedMagnitudes);

  if (!sigma)
  {
    node->L2Error(node->FrobNormSquared() - mu);
    return (node->FrobNormSquared() - mu);
  }

  // Fit a normal distribution using the calculated statistics, and calculate a
  // lower bound on the magnitudes for the passed 'delta' parameter.
  boost::math::normal dist(mu, sigma);
  double lowerBound = boost::math::quantile(dist, delta);

  // Upper bound on the subspace reconstruction error.
  node->L2Error(node->FrobNormSquared() - lowerBound);

  return (node->FrobNormSquared() - lowerBound);
}
コード例 #15
0
BDLSkeletonNode *SimpleSkeletonGrower::pick_branch(bool space_aware)
{
    BDLSkeletonNode *ret(NULL);
    if(!_root)
        return ret;

    //store all possible branches that can be replaced
    std::vector <BDLSkeletonNode *> replaced_candidates;
    std::vector <BDLSkeletonNode *> nodes = bfs();
    for(unsigned int i=0; i<nodes.size(); i++)
    {
        if(nodes[i]->_prev_support)
            replaced_candidates.push_back(nodes[i]);
    }

    //evaulate the probability of each possible candidate
    //then pick the largest one

	//approach 1: grow node with the minimum generation first
	if(!space_aware)
	{
		std::vector <float> probabilities(replaced_candidates.size(), 1.0f);
		int min_gen = -1;
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
		{
			int gen = replaced_candidates[i]->_generation;
			if(gen > 0)
				if(min_gen == -1 || gen < min_gen)
					min_gen = gen;
		}
		//all the min_gen replaced_candidates
		std::vector <BDLSkeletonNode *> min_gen_nodes;
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
			if(replaced_candidates[i]->_generation <= min_gen+3)
				min_gen_nodes.push_back(replaced_candidates[i]);

		if(true)
			if(!min_gen_nodes.empty())
				ret = min_gen_nodes[rand()%min_gen_nodes.size()];

		//do it randomly
		if(false)
			if(!replaced_candidates.empty())
				ret = replaced_candidates[rand()%replaced_candidates.size()];

		return ret;
	}

	//approach 2: grow node which is farest from the volume bound + smaller generation
	if(false && space_aware && _surface.is_loaded())
	{
		//cost = k1*cost_d + k2*cost_g
		//larger closest distance, smaller cost
		//smaller generation, smaller cost
		float min_cost = -1.0f; 
		float k1 = 0.0f, k2 = 1.5f;

		//O(n^2) to find the farest distance of the closest <node, cloud> pair
		//a. find cost_d
		std::vector <float> cost_ds = std::vector <float> (replaced_candidates.size(), 0.0f);
		float largest_d = -1.0f;

		for(unsigned int i=0; i<replaced_candidates.size(); i++)
		{
			osg::Vec3 cur_r = Transformer::toVec3(replaced_candidates[i]);

			float closest = -1.0f;
			for(unsigned int j=0; j<_surface._surface_pts.size(); j++)
			{
				osg::Vec3 cur_s = _surface._surface_pts[j];
				float cur_dist = (cur_r - cur_s).length2();

				if(closest == -1.0f || cur_dist < closest)
					closest = cur_dist;
			}
			cost_ds[i] = closest; 

			if(largest_d == -1.0f || closest > largest_d)
			{
				largest_d = closest;
				ret = replaced_candidates[i];
			}
		}

		//normalize cost_d
		if(largest_d == 0.0f)
			return ret;
		for(unsigned int i=0; i<cost_ds.size(); i++)
			cost_ds[i] /= largest_d;

		//b. find cost_g
		std::vector <float> cost_gs = std::vector <float> (replaced_candidates.size(), 0.0f);
		int largest_g = 0;
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
		{
			int gen = replaced_candidates[i]->_generation;
			cost_gs[i] = gen;
			if(gen > 0)
				if(largest_g == -1 || gen > largest_g)
					largest_g = gen;
		}

		//normalize cost_g
		if(largest_g == 0)
			return ret;
		for(unsigned int i=0; i<cost_gs.size(); i++)
			cost_gs[i] /= float(largest_g);

		//c. caculate costs
		if(largest_g > 8) //hard-coded
			k1 = 0.8f;
		std::vector <float> costs = std::vector <float> (replaced_candidates.size(), 0.0f);
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
			costs[i] = k1 * (1.0f-cost_ds[i]) + k2 * cost_gs[i];

		//d. get min_cost
		for(unsigned int i=0; i<costs.size(); i++)
			if(min_cost == -1.0f || costs[i] < min_cost)
			{
				min_cost = costs[i];
				ret = replaced_candidates[i];
			}
	}

	//approach 3: FOR LATERAL GROWTH, find the longest support branch to replace
	if(false)
	{
		float max_sup_len = -1.0f;
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
		{
			float cur = BDLSkeletonNode::dist(replaced_candidates[i], replaced_candidates[i]->_prev_support);
			if(max_sup_len == -1.0f || cur > max_sup_len)
			{
				max_sup_len = cur;
				ret = replaced_candidates[i];
			}
		}

		return ret;
	}

	//approach 3: find the least projected density among all nodes
	if(true && _surface.is_loaded())
	{
		//a. find the bounds from all surface points
		float right = -1.0f, left = -1.0f, top = -1.0f, bottom = -1.0f;
		for(unsigned int i=0; i<_surface._surface_pts.size(); i++)
		{
			osg::Vec3 cur_s = _surface._surface_pts[i];
			if(right == -1.0f || cur_s.x() > right)
				right = cur_s.x();
			if(left == -1.0f || cur_s.x() < left)
				left = cur_s.x();
			if(top == -1.0f || cur_s.z() > top)
				top = cur_s.z();
			if(bottom == -1.0f || cur_s.z() < bottom)
				bottom = cur_s.z();
		}

		//b. new origin, width, height
		osg::Vec3 origin(left, 0.0f, 0.0f);
		int buff_offset = 50;
		int width = right - left + buff_offset;
		int height = top + buff_offset;
		//printf("w(%d) h(%d)\n", width, height);

		//c. density map
		std::vector <std::vector <int> > density_map(width, std::vector <int>(height, 0));

		//d1. initialize density map with all nodes
		for(unsigned int i=0; i<nodes.size(); i++)
		{
			BDLSkeletonNode *node = nodes[i];
			osg::Vec3 punch = Transformer::toVec3(node) - origin;

			if(punch.z() < bottom)
				continue;

			//vote around point punch
			for(int j=-3; j<6; j++)
				for(int k=-3; k<6; k++)
				{
					//printf("x(%d) y(%d)\n", int(punch.x()+j), int(punch.z()+k));
					int int_j = punch.x() + j;
					int int_k = punch.z() + k;

					if(int_j >= 0 && int_k >= 0)
						density_map[int_j][int_k]++;
				}
		}
		//d2. initialize density map with simple pruner
		for(int i=0; i<width; i++)
			for(int j=0; j<height; j++)
			{
				osg::Vec3 field = origin + osg::Vec3(i, 0.0f, j);
				if(!_pruner.is_inside_ortho(field))
					density_map[i][j] = -10;//99999; //means forbidden or infinitely dense
			}

		//test: obtain convex hull of replaced_candidates
		if(_approaching_done) //if approaching the end of the process
		{
			std::vector <osg::Vec2> r_can;
			for(unsigned int i=0; i<replaced_candidates.size(); i++)
				if(_pruner.is_inside_ortho(Transformer::toVec3(replaced_candidates[i])))
					r_can.push_back(osg::Vec2(replaced_candidates[i]->_sx, replaced_candidates[i]->_sz));

			ConvexHull2D hull;
			hull.load_points(r_can);
			std::vector <int> hull_idx = hull.work();
			std::vector <BDLSkeletonNode *> replaced_candidates_hull;
			for(unsigned int i=0; i<hull_idx.size(); i++)
				replaced_candidates_hull.push_back(replaced_candidates[hull_idx[i]]);
			replaced_candidates = replaced_candidates_hull;
		}

		//e. find the least density point
		std::vector <float> cost_ds = std::vector <float> (replaced_candidates.size(), 0.0f);
		float largest_d = -1.0f;

		long long least_dense_value = -1;
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
		{
			BDLSkeletonNode *node = replaced_candidates[i];
			osg::Vec3 punch = Transformer::toVec3(node) - origin;

			if(punch.x() >= 0 && punch.x() < width-1 && punch.z() >= 0 && punch.z() < height-1)
				if(density_map[punch.x()][punch.z()] < 0)
					continue;

			long long sum = 0;

			//sum up the votes around the punch
			for(int j=-3; j<6; j++)
				for(int k=-3; k<6; k++)
				{

					int int_j = punch.x() + j;
					int int_k = punch.z() + k;

					if(int_j >= 0 && int_k >= 0)
						sum += density_map[int_j][int_k];
				}

			cost_ds[i] = sum;
			if(largest_d == -1.0f || sum > largest_d)
				largest_d = sum;

			if(least_dense_value == -1 || sum < least_dense_value)
			{
				least_dense_value = sum;
				ret = replaced_candidates[i];
			}
		}

		//f. normalize cost_ds
		if(largest_d == -1.0f)
			return ret;
		for(unsigned int i=0; i<cost_ds.size(); i++)
			cost_ds[i] /= float(largest_d);

		//g. find the lenghts of the replacement rods
		std::vector <float> cost_ls = std::vector <float> (replaced_candidates.size(), 0.0f);
		float largest_l = -1.0f;
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
		{
			float len = (Transformer::toVec3(replaced_candidates[i]) - Transformer::toVec3(replaced_candidates[i]->_prev_support)).length2();
			cost_ls[i] = len;
			if(largest_l == -1.0f || len > largest_l)
				largest_l = len;
		}

		//h. normalize cost_gs
		if(largest_l == 0)
			return ret;
		for(unsigned int i=0; i<cost_ls.size(); i++)
			cost_ls[i] /= float(largest_l);

		//i. caculate costs
		int k1 = 0.4f, k2 = 0.6f;
		std::vector <float> costs = std::vector <float> (replaced_candidates.size(), 0.0f);
		for(unsigned int i=0; i<replaced_candidates.size(); i++)
			costs[i] = k1 * (1.0f-cost_ls[i]) + k2 * cost_ds[i];

		//j. get min_cost
		float min_cost = -1.0f;
		for(unsigned int i=0; i<costs.size(); i++)
			if(min_cost == -1.0f || costs[i] < min_cost)
			{
				min_cost = costs[i];
				ret = replaced_candidates[i];
			}
	}

    return ret;
}