/** * \brief TODO */ double DistributionMixtureModel::getComponentProb(const std::vector<double>& instance, const size_t component) const { size_t K = this->numberOfComponents(); if (instance.size() != 1) { stringstream msg; msg << "DistributionMixtureModel - instance must be " << "described by single value, but found " << instance.size(); throw MixtureModelException(msg.str()); } double val = instance[0]; // calculate z's vector<double> z; for (size_t k=0; k<K; k++) { z.push_back(log(this->mixing[k]) + this->ds[k]->loglikelihood(val)); } // find max z and get sum over k double m = *max_element(z.begin(), z.end()); double d = 0; for (size_t k=0; k<K; k++) d += exp(z[k] - m); return exp(z[component] - m) / d; }
int main(int argc, char** argv) { bool usage = static_cast<bool>(pick_option(&argc, argv, "h", nullptr)); bool bar = static_cast<bool>(pick_option(&argc, argv, "b", nullptr)); float m = static_cast<float>(atof(pick_option(&argc, argv, "m", "nan"))); float M = static_cast<float>(atof(pick_option(&argc, argv, "M", "nan"))); if (usage) { cerr << "usage: " << argv[0] << " [mask [output]] [-m minval] " << "[-M maxval] [-b]" << endl; return EXIT_SUCCESS; } Image mask = read_image(argc > 1 ? argv[1] : "-"); if (std::isnan(m)) m = *min_element(mask.begin(), mask.end()); if (std::isnan(M)) M = *max_element(mask.begin(), mask.end()); if (mask.channels() != 1) { cerr << "The mask should have one channel." << endl; return EXIT_FAILURE; } if (m >= M) { cerr << "m should be smaller than M." << endl; return EXIT_FAILURE; } Image out = apply_colormap(mask, m, M, bar); save_image(out, argc > 2 ? argv[2] : "TIFF:-"); return EXIT_SUCCESS; }
void CDrawGraph::OnPaint() { CPaintDC dc(this); // device context for painting CConvertToSPEXDoc* pDoc = GetMyDocument(); dc.MoveTo(0,0); // dc.LineTo(10,10); if(pDoc->fpdata.empty()) return; float f1 = *min_element(pDoc->fpdata.begin(), pDoc->fpdata.end()); float f2 = *max_element(pDoc->fpdata.begin(), pDoc->fpdata.end()); if(f1 == f2) f2++; CRect cr; GetWindowRect(cr); float w = cr.Width(); float h = cr.Height(); dc.MoveTo(0,h - (pDoc->fpdata[0]-f1)/(f1-f2)*h); for(int i=0; i < pDoc->fpdata.size(); i++) { dc.LineTo( i*w/pDoc->fpdata.size() , (pDoc->fpdata[i]-f1)/(f2-f1)*-h +h ); } }
void Lock(const size_t threadNum) { choosing[threadNum] = true; turn[threadNum] = *max_element(turn, turn + MAX_THREADS_COUNT) + 1; choosing[threadNum] = false; for (size_t i = 0; i < MAX_THREADS_COUNT; ++i) { while (choosing[i]); while (turn[i] != 0 && (turn[i] < turn[threadNum] || (turn[i] == turn[threadNum] && i < threadNum))); } }
/** * \brief log-likelihood that a given vector of observations was produced * by this mixture * \note we scale values in log-space to avoid an underflow */ double DistributionMixtureModel::loglikelihood(const std::vector<double> &obs) const { size_t N = obs.size(), K = this->numberOfComponents(); double sum = 0; for (size_t i=0; i<N; i++) { // calculate z's for this i vector<double> z; for (size_t k=0; k<K; k++) { double zi = log(this->mixing[k]) + this->ds[k]->loglikelihood(obs[i]); z.push_back(zi); } // find max z and get sum over k double m = *max_element(z.begin(), z.end()); double d = 0; for (size_t k=0; k<K; k++) d += exp(z[k] - m); // add contribution from ith observation sum += (m + log(d)); } return sum; }
MzSpectrum normalize(MzSpectrum const &mzSpectrum, types::intensity_t const normalizeTo) { using std::make_pair; using std::max_element; using types::intensity_t; using types::intensity_store_t; MzSpectrum normalizedSpectrum(mzSpectrum); intensity_t const maxInt = (max_element(mzSpectrum.begin(), mzSpectrum.end(), smallerIntensity))->second; // The spectrum's max intensity intensity_store_t const maxScale = normalizeTo/maxInt; for(auto &mzSpecPair : normalizedSpectrum) { mzSpecPair.second = mzSpecPair.second * maxScale; } return normalizedSpectrum; }
size_t ArgMax(const VectorL<T>& v) { return v.beginRow_ + distance(v.storage_.begin(), max_element(v.storage_.begin(), v.storage_.end())); }
T Max(const VectorL<T>& v) { return *max_element(v.storage_.begin(), v.storage_.end()); }
void AnalogSnapshot::append_payload_to_envelope_levels() { Envelope &e0 = _envelope_levels[0]; uint64_t prev_length; EnvelopeSample *dest_ptr; // Expand the data buffer to fit the new samples prev_length = e0.length; e0.length = _sample_count / EnvelopeScaleFactor; // Break off if there are no new samples to compute if (e0.length == prev_length) return; reallocate_envelope(e0); dest_ptr = e0.samples + prev_length; // Iterate through the samples to populate the first level mipmap const float *const end_src_ptr = (float*)_data + e0.length * EnvelopeScaleFactor; for (const float *src_ptr = (float*)_data + prev_length * EnvelopeScaleFactor; src_ptr < end_src_ptr; src_ptr += EnvelopeScaleFactor) { const EnvelopeSample sub_sample = { *min_element(src_ptr, src_ptr + EnvelopeScaleFactor), *max_element(src_ptr, src_ptr + EnvelopeScaleFactor), }; *dest_ptr++ = sub_sample; } // Compute higher level mipmaps for (unsigned int level = 1; level < ScaleStepCount; level++) { Envelope &e = _envelope_levels[level]; const Envelope &el = _envelope_levels[level-1]; // Expand the data buffer to fit the new samples prev_length = e.length; e.length = el.length / EnvelopeScaleFactor; // Break off if there are no more samples to computed if (e.length == prev_length) break; reallocate_envelope(e); // Subsample the level lower level const EnvelopeSample *src_ptr = el.samples + prev_length * EnvelopeScaleFactor; const EnvelopeSample *const end_dest_ptr = e.samples + e.length; for (dest_ptr = e.samples + prev_length; dest_ptr < end_dest_ptr; dest_ptr++) { const EnvelopeSample *const end_src_ptr = src_ptr + EnvelopeScaleFactor; EnvelopeSample sub_sample = *src_ptr++; while (src_ptr < end_src_ptr) { sub_sample.min = min(sub_sample.min, src_ptr->min); sub_sample.max = max(sub_sample.max, src_ptr->max); src_ptr++; } *dest_ptr = sub_sample; } } }
int main(int argc, char **argv) { //Create a CMT object Config config("FAST", "BRISK","RANSAC",0.5); CMT cmt(config); //Initialization bounding box Rect rect; //Parse args int challenge_flag = 0; int loop_flag = 0; int verbose_flag = 0; int bbox_flag = 0; int skip_frames = 0; int skip_msecs = 0; int output_flag = 0; string input_path; string output_path; const int detector_cmd = 1000; const int descriptor_cmd = 1001; const int bbox_cmd = 1002; const int no_scale_cmd = 1003; const int with_rotation_cmd = 1004; const int skip_cmd = 1005; const int skip_msecs_cmd = 1006; const int output_file_cmd = 1007; struct option longopts[] = { //No-argument options {"challenge", no_argument, &challenge_flag, 1}, {"loop", no_argument, &loop_flag, 1}, {"verbose", no_argument, &verbose_flag, 1}, {"no-scale", no_argument, 0, no_scale_cmd}, {"with-rotation", no_argument, 0, with_rotation_cmd}, //Argument options {"bbox", required_argument, 0, bbox_cmd}, {"detector", required_argument, 0, detector_cmd}, {"descriptor", required_argument, 0, descriptor_cmd}, {"output-file", required_argument, 0, output_file_cmd}, {"skip", required_argument, 0, skip_cmd}, {"skip-msecs", required_argument, 0, skip_msecs_cmd}, {0, 0, 0, 0} }; int index = 0; int c; while((c = getopt_long(argc, argv, "v", longopts, &index)) != -1) { switch (c) { case 'v': verbose_flag = true; break; case bbox_cmd: { //TODO: The following also accepts strings of the form %f,%f,%f,%fxyz... string bbox_format = "%f,%f,%f,%f"; float x,y,w,h; int ret = sscanf(optarg, bbox_format.c_str(), &x, &y, &w, &h); if (ret != 4) { cerr << "bounding box must be given in format " << bbox_format << endl; return 1; } bbox_flag = 1; rect = Rect(x,y,w,h); } break; case detector_cmd: cmt.str_detector = optarg; break; case descriptor_cmd: cmt.str_descriptor = optarg; break; case output_file_cmd: output_path = optarg; output_flag = 1; break; case skip_cmd: { int ret = sscanf(optarg, "%d", &skip_frames); if (ret != 1) { skip_frames = 0; } } break; case skip_msecs_cmd: { int ret = sscanf(optarg, "%d", &skip_msecs); if (ret != 1) { skip_msecs = 0; } } break; case no_scale_cmd: cmt.consensus.estimate_scale = false; break; case with_rotation_cmd: cmt.consensus.estimate_rotation = true; break; case '?': return 1; } } // Can only skip frames or milliseconds, not both. if (skip_frames > 0 && skip_msecs > 0) { cerr << "You can only skip frames, or milliseconds, not both." << endl; return 1; } //One argument remains if (optind == argc - 1) { input_path = argv[optind]; } else if (optind < argc - 1) { cerr << "Only one argument is allowed." << endl; return 1; } //Set up logging FILELog::ReportingLevel() = verbose_flag ? logDEBUG : logINFO; Output2FILE::Stream() = stdout; //Log to stdout //Challenge mode if (challenge_flag) { //Read list of images ifstream im_file("images.txt"); vector<string> files; string line; while(getline(im_file, line )) { files.push_back(line); } //Read region ifstream region_file("region.txt"); vector<float> coords = getNextLineAndSplitIntoFloats(region_file); if (coords.size() == 4) { rect = Rect(coords[0], coords[1], coords[2], coords[3]); } else if (coords.size() == 8) { //Split into x and y coordinates vector<float> xcoords; vector<float> ycoords; for (size_t i = 0; i < coords.size(); i++) { if (i % 2 == 0) xcoords.push_back(coords[i]); else ycoords.push_back(coords[i]); } float xmin = *min_element(xcoords.begin(), xcoords.end()); float xmax = *max_element(xcoords.begin(), xcoords.end()); float ymin = *min_element(ycoords.begin(), ycoords.end()); float ymax = *max_element(ycoords.begin(), ycoords.end()); rect = Rect(xmin, ymin, xmax-xmin, ymax-ymin); cout << "Found bounding box" << xmin << " " << ymin << " " << xmax-xmin << " " << ymax-ymin << endl; } else { cerr << "Invalid Bounding box format" << endl; return 0; } //Read first image Mat im0 = imread(files[0]); Mat im0_gray; cvtColor(im0, im0_gray, CV_BGR2GRAY); //Initialize cmt cmt.initialize(im0_gray, rect); //Write init region to output file ofstream output_file("output.txt"); output_file << rect.x << ',' << rect.y << ',' << rect.width << ',' << rect.height << std::endl; //Process images, write output to file for (size_t i = 1; i < files.size(); i++) { FILE_LOG(logINFO) << "Processing frame " << i << "/" << files.size(); Mat im = imread(files[i]); Mat im_gray; cvtColor(im, im_gray, CV_BGR2GRAY); cmt.processFrame(im_gray); if (verbose_flag) { display(im, cmt); } rect = cmt.bb_rot.boundingRect(); output_file << rect.x << ',' << rect.y << ',' << rect.width << ',' << rect.height << std::endl; } output_file.close(); return 0; } //Normal mode //Create window namedWindow(WIN_NAME); VideoCapture cap; bool show_preview = true; //If no input was specified if (input_path.length() == 0) { cap.open(0); //Open default camera device } //Else open the video specified by input_path else { cap.open(input_path); if (skip_frames > 0) { cap.set(CV_CAP_PROP_POS_FRAMES, skip_frames); } if (skip_msecs > 0) { cap.set(CV_CAP_PROP_POS_MSEC, skip_msecs); // Now which frame are we on? skip_frames = (int) cap.get(CV_CAP_PROP_POS_FRAMES); } show_preview = false; } //If it doesn't work, stop if(!cap.isOpened()) { cerr << "Unable to open video capture." << endl; return -1; } //Show preview until key is pressed while (show_preview) { Mat preview; cap >> preview; screenLog(preview, "Press a key to start selecting an object."); imshow(WIN_NAME, preview); char k = waitKey(10); if (k != -1) { show_preview = false; } } //Get initial image Mat im0; cap >> im0; //If no bounding was specified, get it from user if (!bbox_flag) { rect = getRect(im0, WIN_NAME); } FILE_LOG(logINFO) << "Using " << rect.x << "," << rect.y << "," << rect.width << "," << rect.height << " as initial bounding box."; //Convert im0 to grayscale Mat im0_gray; if (im0.channels() > 1) { cvtColor(im0, im0_gray, CV_BGR2GRAY); } else { im0_gray = im0; } //Initialize CMT cmt.initialize(im0_gray, rect); int frame = skip_frames; //Open output file. ofstream output_file; if (output_flag) { int msecs = (int) cap.get(CV_CAP_PROP_POS_MSEC); output_file.open(output_path.c_str()); output_file << OUT_FILE_COL_HEADERS << endl; output_file << frame << "," << msecs << ","; output_file << cmt.points_active.size() << ","; output_file << write_rotated_rect(cmt.bb_rot) << endl; } //Main loop while (true) { frame++; Mat im; //If loop flag is set, reuse initial image (for debugging purposes) if (loop_flag) im0.copyTo(im); else cap >> im; //Else use next image in stream if (im.empty()) break; //Exit at end of video stream Mat im_gray; if (im.channels() > 1) { cvtColor(im, im_gray, CV_BGR2GRAY); } else { im_gray = im; } //Let CMT process the frame cmt.processFrame(im_gray); //Output. if (output_flag) { int msecs = (int) cap.get(CV_CAP_PROP_POS_MSEC); output_file << frame << "," << msecs << ","; output_file << cmt.points_active.size() << ","; output_file << write_rotated_rect(cmt.bb_rot) << endl; } else { //TODO: Provide meaningful output FILE_LOG(logINFO) << "#" << frame << " active: " << cmt.points_active.size(); } //Display image and then quit if requested. char key = display(im, cmt); if(key == 'q') break; } //Close output file. if (output_flag) output_file.close(); return 0; }
void PathInfo::calcLBAndNextEdge(const AdjMat& c) { // information about the useable matrix struct MatrixInfo info(c.size); // calculate the initial LB from edges already included // also, set any edges that would create a subtour as infinite this->setAvailAndLB(c, info); // reduce the matrix, increment the lower bound from the reduction this->lowerBound += info.reduceMatrix(c, *this); // find all the zeros in the matrix vector<Edge> zeros; for(unsigned int i = 0; i < c.size; ++i) { if(info.rowAvail[i]) { for(unsigned int j = 0; j < c.size; ++j) { if(info.colAvail[j] && !this->isInfinite(i, j)) { if(c(i, j) - info.rowReds[i] - info.colReds[j] == 0) { zeros.push_back({ i, j }); } } } } } // get a penalty associated with each zero vector<unsigned int> penalties(zeros.size()); unsigned int counter = 0; for(const Edge zero : zeros) { bool foundMinCol = false; bool foundMinRow = false; unsigned int minCol = infinity; unsigned int minRow = infinity; // check for largest distance in row for(unsigned int i = 0; i < c.size; ++i) { // INVARIANT: column is always available if(info.rowAvail[i] && !this->isInfinite(i, zero.second) && i != zero.first && c(i, zero.second) - info.rowReds[i] - info.colReds[zero.second] < minRow) { minRow = c(i, zero.second) - info.rowReds[i] - info.colReds[zero.second]; foundMinRow = true; } } // check largest distance in col for(unsigned int j = 0; j < c.size; ++j) { // INVARIANT: row is always available if(info.colAvail[j] && !this->isInfinite(zero.first, j) && zero.second != j && c(zero.first, j) - info.rowReds[zero.first] - info.colReds[j] < minCol) { minCol = c(zero.first, j) - info.rowReds[zero.first] - info.colReds[j]; foundMinCol = true; } } // 3 cases // 1. base case if(c.size - this->include.size() == 2) { penalties[counter++] = infinity; break; } // 2. case when excluding the node creates a disconnected graph else if(foundMinCol != foundMinRow && c.size - this->include.size() != 2) { // we must choose this edge and cannot branch this->next = zero; this->bothBranches = false; return; } // 3. normal case, there is both an include and exclude branch else { penalties[counter++] = minRow + minCol; } } // set the next edge as the zero with the highest penalty auto maxPenaltyIt = max_element(penalties.begin(), penalties.end()); unsigned int index = maxPenaltyIt - penalties.begin(); // handle the base case if(c.size - this->include.size() == 2) { this->addInclude(zeros[index]); info.rowAvail[zeros[index].first] = false; info.colAvail[zeros[index].second] = false; unsigned int row = 0; unsigned int col = 0; // INVARIANT: only one valid edge left, find it for(unsigned int i = 0; i < info.rowAvail.size(); ++i) { if(info.rowAvail[i]) { row = i; break; } } for(unsigned int j = 0; j < info.colAvail.size(); ++j) { if(info.colAvail[j]) { col = j; break; } } this->addInclude({ row, col }); // recalculate LB, the length of the TSP tour this->setAvailAndLB(c, info); throw NoNextEdge(); } // for any other case, set the next edge to branch on // and set the flag that calculations have been completed this->next = zeros[index]; this->foundLBAndEdge = true; }
//! Execute random walk simulator application mode. void executeRandomWalkSimulator( const std::string databasePath, const tudat::input_output::parsed_data_vector_utilities::ParsedDataVectorPtr parsedData ) { /////////////////////////////////////////////////////////////////////////// // Declare using-statements. using std::advance; using std::cerr; using std::cout; using std::endl; using std::max_element; using std::min_element; using std::numeric_limits; using std::ofstream; using std::ostringstream; using std::setprecision; using std::string; using boost::iequals; using namespace boost::filesystem; using boost::make_shared; using namespace assist::astrodynamics; using namespace assist::basics; using namespace assist::mathematics; using namespace tudat::basic_astrodynamics::orbital_element_conversions; using namespace tudat::basic_mathematics::mathematical_constants; using namespace tudat::input_output; using namespace tudat::input_output::dictionary; using namespace tudat::statistics; using namespace stomi::astrodynamics; using namespace stomi::database; using namespace stomi::input_output; /////////////////////////////////////////////////////////////////////////// // Extract input parameters. // Get dictionary. const DictionaryPointer dictionary = getRandomWalkSimulatorDictionary( ); // Print database path to console. cout << "Database " << databasePath << endl; // Extract required parameters. const string randomWalkRunName = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "RANDOMWALKRUN" ) ); cout << "Random walk run " << randomWalkRunName << endl; // Extract optional parameters. const int numberOfThreads = extractParameterValue< int >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "NUMBEROFTHREADS" ), 1 ); cout << "Number of threads " << numberOfThreads << endl; const string outputMode = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "OUTPUTMODE" ), "DATABASE" ); cout << "Output mode " << outputMode << endl; const string fileOutputDirectory = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "FILEOUTPUTDIRECTORY" ), "" ) + "/"; cout << "File output directory " << fileOutputDirectory << endl; const string randomWalkSimulations = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "RANDOMWALKSIMULATIONS" ), "ALL" ); cout << "Random walk simulations " << randomWalkSimulations << endl; const string randomWalkRunTableName = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "RANDOMWALKRUNTABLENAME" ), "random_walk_run" ); cout << "Random walk run table " << randomWalkRunTableName << endl; const string randomWalkInputTableName = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "RANDOMWALKINPUTTABLENAME" ), "random_walk_input" ); cout << "Random walk input table " << randomWalkInputTableName << endl; const string randomWalkPerturberTableName = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "RANDOMWALKPERTURBERTABLENAME" ), "random_walk_perturbers" ); cout << "Random walk perturber table " << randomWalkPerturberTableName << endl; const string randomWalkOutputTableName = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "RANDOMWALKOUTPUTTABLENAME" ), "random_walk_output" ); cout << "Random walk output table " << randomWalkOutputTableName << endl; const string testParticleCaseTableName = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "TESTPARTICLECASETABLENAME" ), "test_particle_case" ); cout << "Test particle case table " << testParticleCaseTableName << endl; const string testParticleKickTableName = extractParameterValue< string >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "TESTPARTICLEKICKTABLENAME" ), "test_particle_kicks" ); cout << "Test particle kick table " << testParticleKickTableName << endl; // Retrieve and store random walk run data from database. RandomWalkRunPointer randomWalkRun; // Random walk run data is extracted in local scope from the database, with overwritten // parameters extracted from the input file, to ensure that none of these parameters are used // globally elsewhere in this file. { const RandomWalkRunPointer retrievedRandomWalkRun = getRandomWalkRun( databasePath, randomWalkRunName, randomWalkRunTableName ); const double perturberRingNumberDensity = extractParameterValue< double >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "PERTURBERRINGNUMBERDENSITY" ), retrievedRandomWalkRun->perturberRingNumberDensity ); cout << "Perturber ring number density " << perturberRingNumberDensity << " perturbers per R_Hill" << endl; const double perturberRingMass = extractParameterValue< double >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "PERTURBERRINGMASS" ), retrievedRandomWalkRun->perturberRingMass ); cout << "Perturber ring mass " << perturberRingMass << " M_PerturbedBody" << endl; const double observationPeriod = extractParameterValue< double >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "OBSERVATIONPERIOD" ), retrievedRandomWalkRun->observationPeriod, &convertJulianYearsToSeconds ); cout << "Observation period " << convertSecondsToJulianYears( observationPeriod ) << " yrs" << endl; const unsigned int numberOfEpochWindows = extractParameterValue< unsigned int >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "NUMBEROFEPOCHWINDOWS" ), retrievedRandomWalkRun->numberOfEpochWindows ); cout << "Number of epoch windows " << numberOfEpochWindows << endl; const double epochWindowSize = extractParameterValue< double >( parsedData->begin( ), parsedData->end( ), findEntry( dictionary, "EPOCHWINDOWSIZE" ), retrievedRandomWalkRun->epochWindowSize, &convertJulianDaysToSeconds ); cout << "Epoch window size " << convertSecondsToJulianDays( epochWindowSize ) << " days" << endl; // Store random walk run data with possible overwritten data. randomWalkRun = make_shared< RandomWalkRun >( retrievedRandomWalkRun->randomWalkRunId, randomWalkRunName, retrievedRandomWalkRun->testParticleCaseId, perturberRingNumberDensity, perturberRingMass, observationPeriod, numberOfEpochWindows, epochWindowSize ); } // Check that all required parameters have been set. checkRequiredParameters( dictionary ); /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Fetch test particle case and random walk input data from database. cout << endl; cout << "****************************************************************************" << endl; cout << "Database operations" << endl; cout << "****************************************************************************" << endl; cout << endl; // Generate output message. cout << "Fetching test particle case data from database ..." << endl; // Retrieve and store test particle case data. const TestParticleCasePointer testParticleCaseData = getTestParticleCase( databasePath, randomWalkRun->testParticleCaseId, testParticleCaseTableName ); // Generate output message to indicate that test particle case data was fetched successfully. cout << "Test particle case data fetched successfully from database!" << endl; // Generate output message. cout << "Fetching random walk input data from database ..." << endl; // Check if all incomplete random walk simulations are to be executed and fetch the random // walk input table, else only fetch the requested random walk simulation IDs. RandomWalkInputTable randomWalkInputTable; if ( iequals( randomWalkSimulations, "ALL" ) ) { cout << "Fetching all incomplete random walk Monte Carlo runs ..." << endl; // Get entire random walk input table from database. randomWalkInputTable = getCompleteRandomWalkInputTable( databasePath, randomWalkRun->randomWalkRunId, randomWalkInputTableName, randomWalkPerturberTableName ); } else { cout << "Fetching all requested random walk Monte Carlo runs ..." << endl; // Get selected random walk input table from database. randomWalkInputTable = getSelectedRandomWalkInputTable( databasePath, randomWalkRun->randomWalkRunId, randomWalkSimulations, randomWalkInputTableName, randomWalkPerturberTableName ); } // Generate output message to indicate that the input table was fetched successfully. cout << "Random walk input data (" << randomWalkInputTable.size( ) << " rows) fetched successfully from database!" << endl; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Compute derived parameters. cout << endl; cout << "****************************************************************************" << endl; cout << "Derived parameters" << endl; cout << "****************************************************************************" << endl; cout << endl; // Compute epoch window spacing [s]. const double epochWindowSpacing = randomWalkRun->observationPeriod / ( randomWalkRun->numberOfEpochWindows - 1 ); cout << "Epoch window spacing " << convertSecondsToJulianDays( epochWindowSpacing ) << " days" << endl; // Compute mass of perturbed body [kg]. const double perturbedBodyMass = computeMassOfSphere( testParticleCaseData->perturbedBodyRadius, testParticleCaseData->perturbedBodyBulkDensity ); cout << "Perturbed body mass " << perturbedBodyMass << " kg" << endl; // Compute perturbed body's gravitational parameter [m^3 s^-2]. const double perturbedBodyGravitationalParameter = computeGravitationalParameter( perturbedBodyMass ); cout << "Perturbed body gravitational parameter " << perturbedBodyGravitationalParameter << " m^3 s^-2" << endl; // Compute perturber population using density and semi-major axis distribution limits. // Note, in the floor() function, adding 0.5 is a workaround for the fact that there is no // round() function in C++03 (it is available in C++11). ConvertHillRadiiToMeters convertHillRadiiToMeters( testParticleCaseData->centralBodyGravitationalParameter, perturbedBodyGravitationalParameter, testParticleCaseData->perturbedBodyStateInKeplerianElementsAtT0( semiMajorAxisIndex ) ); const double perturberRingNumberDensityInMeters = randomWalkRun->perturberRingNumberDensity / convertHillRadiiToMeters( 1.0 ); const unsigned int perturberPopulation = std::floor( 2.0 * testParticleCaseData->semiMajorAxisDistributionLimit * perturberRingNumberDensityInMeters + 0.5 ); cout << "Perturber population " << perturberPopulation << endl; // Compute perturber mass ratio. // Note, for the random walk simulations, the mass ratio is equal for all perturbers. const double perturberMassRatio = randomWalkRun->perturberRingMass / perturberPopulation; cout << "Perturber mass ratio " << perturberMassRatio << endl; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Execute Monte Carlo simulation. cout << endl; cout << "****************************************************************************" << endl; cout << "Simulation loop" << endl; cout << "****************************************************************************" << endl; cout << endl; // Execute simulation loop. cout << "Starting simulation loop ... " << endl; cout << randomWalkInputTable.size( ) << " random walk simulations queued for execution ..." << endl; cout << endl; // Loop over input table. #pragma omp parallel for num_threads( numberOfThreads ) for ( unsigned int i = 0; i < randomWalkInputTable.size( ); i++ ) { /////////////////////////////////////////////////////////////////////////// // Set input table iterator and emit output message. // Set input table iterator for current simulation wrt to start of input table and counter. RandomWalkInputTable::iterator iteratorRandomWalkInputTable = randomWalkInputTable.begin( ); advance( iteratorRandomWalkInputTable, i ); // Emit output message. #pragma omp critical( outputToConsole ) { cout << "Random walk simulation " << iteratorRandomWalkInputTable->randomWalkSimulationId << " on thread " << omp_get_thread_num( ) + 1 << " / " << omp_get_num_threads( ) << endl; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Fetch test particle kick table based on test particle simulation IDs for random walk // simulation. TestParticleKickTable testParticleKickTable; #pragma omp critical( databaseOperations ) { testParticleKickTable = getTestParticleKickTable( databasePath, testParticleCaseData->randomWalkSimulationPeriod, iteratorRandomWalkInputTable->testParticleSimulationIds, testParticleKickTableName ); } // Check if output mode is set to "FILE". // If so, open output file and write test particle kick table data. // Check if the output directory exists: if not, create it. if ( iequals( outputMode, "FILE" ) ) { // Check if output directory exists. if ( !exists( fileOutputDirectory ) ) { cerr << "Directory does not exist. Will be created." << endl; create_directories( fileOutputDirectory ); } // Declare file handler. ofstream testParticleKickTableFile; // Set up and write file header to file. ostringstream testParticleKickTableFilename; testParticleKickTableFilename << fileOutputDirectory << "randomWalkSimulation" << iteratorRandomWalkInputTable->randomWalkSimulationId << "_testParticleKickTable.csv"; testParticleKickTableFile.open( testParticleKickTableFilename.str( ).c_str( ) ); testParticleKickTableFile << "kickId,simulationId,conjunctionEpoch,conjunctionDistance," << "preConjunctionEpoch,preConjunctionDistance," << "preConjunctionSemiMajorAxis,preConjunctionEccentricity," << "preConjunctionInclination,preConjunctionArgumentOfPeriapsis," << "preConjunctionLongitudeOfAscendingNode,preConjunctionTrueAnomaly" << "postConjunctionEpoch,postConjunctionDistance," << "postConjunctionSemiMajorAxis,postConjunctionEccentricity," << "postConjunctionInclination,postConjunctionArgumentOfPeriapsis," << "postConjunctionLongitudeOfAscendingNode,postConjunctionTrueAnomaly" << endl; testParticleKickTableFile << "# [-],[-],[s],[m],[s],[m],[m],[-],[rad],[rad],[rad],[rad]," << "[s],[m],[m],[-],[rad],[rad],[rad],[rad]" << endl; // Write test particle kick table to file. for ( TestParticleKickTable::iterator iteratorTestParticleKicks = testParticleKickTable.begin( ); iteratorTestParticleKicks != testParticleKickTable.end( ); iteratorTestParticleKicks++ ) { testParticleKickTableFile << iteratorTestParticleKicks->testParticleKickId << "," << iteratorTestParticleKicks->testParticleSimulationId << ","; testParticleKickTableFile << setprecision( numeric_limits< double >::digits10 ) << iteratorTestParticleKicks->conjunctionEpoch << "," << iteratorTestParticleKicks->conjunctionDistance << "," << iteratorTestParticleKicks->preConjunctionEpoch << "," << iteratorTestParticleKicks->preConjunctionDistance << "," << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( semiMajorAxisIndex ) << "," << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( eccentricityIndex ) << "," << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( inclinationIndex ) << "," << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( argumentOfPeriapsisIndex ) << "," << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( longitudeOfAscendingNodeIndex ) << "," << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( trueAnomalyIndex ) << "," << iteratorTestParticleKicks->postConjunctionEpoch << "," << iteratorTestParticleKicks->postConjunctionDistance << "," << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( semiMajorAxisIndex ) << "," << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( eccentricityIndex ) << "," << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( inclinationIndex ) << "," << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( argumentOfPeriapsisIndex ) << "," << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( longitudeOfAscendingNodeIndex ) << "," << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( trueAnomalyIndex ) << endl; } // Close file handler. testParticleKickTableFile.close( ); } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Execute random walk simulation. // Declare perturbed body propagation history. This stores the propagation history of the // action variables only (semi-major axis, eccentricity, inclination). DoubleKeyVector3dValueMap keplerianActionElementsHistory; // Set perturbed body initial state (actions) in Keplerian elements. keplerianActionElementsHistory[ 0.0 ] = testParticleCaseData->perturbedBodyStateInKeplerianElementsAtT0.segment( 0, 3 ); // Declare iterator to previous state in Keplerian elements. DoubleKeyVector3dValueMap::iterator iteratorPreviousKeplerianElements = keplerianActionElementsHistory.begin( ); // Loop through aggregate kick table and execute kicks on perturbed body. for ( TestParticleKickTable::iterator iteratorKickTable = testParticleKickTable.begin( ); iteratorKickTable != testParticleKickTable.end( ); iteratorKickTable++ ) { // Execute kick and store results in propagation history. keplerianActionElementsHistory[ iteratorKickTable->conjunctionEpoch ] = executeKick( iteratorPreviousKeplerianElements->second, iteratorKickTable, perturberMassRatio ); advance( iteratorPreviousKeplerianElements, 1 ); } // Check if output mode is set to "FILE". // If so, open output file and write header content. if ( iequals( outputMode, "FILE" ) ) { ostringstream keplerianActionElementsFilename; keplerianActionElementsFilename << "randomWalkSimulation" << iteratorRandomWalkInputTable->randomWalkSimulationId << "_keplerianActionElements.csv"; ostringstream keplerianActionElementsFileHeader; keplerianActionElementsFileHeader << "epoch,semiMajorAxis,eccentricity,inclination" << endl; keplerianActionElementsFileHeader << "# [s],[m],[-],[rad]" << endl; writeDataMapToTextFile( keplerianActionElementsHistory, keplerianActionElementsFilename.str( ), fileOutputDirectory, keplerianActionElementsFileHeader.str( ), numeric_limits< double >::digits10, numeric_limits< double >::digits10, "," ); } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Compute average longitude residual and maximum longitude residual change in observation // period. // Declare average longitude residual in observation period [-]. double averageLongitudeResidual = TUDAT_NAN; // Declare maximum longitude residual change in observation period [-]. double maximumLongitudeResidualChange = TUDAT_NAN; // Declare map of average longitude residuals per window [rad]. DoubleKeyDoubleValueMap averageLongitudeResiduals; { // Populate temporary map with epochs and semi-major axes. DoubleKeyDoubleValueMap semiMajorAxisHistory; for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements = keplerianActionElementsHistory.begin( ); iteratorKeplerianActionElements != keplerianActionElementsHistory.end( ); iteratorKeplerianActionElements++ ) { semiMajorAxisHistory[ iteratorKeplerianActionElements->first ] = iteratorKeplerianActionElements->second( semiMajorAxisIndex ); } // Compute longitude history. DoubleKeyDoubleValueMap longitudeHistory = computeLongitudeHistory( semiMajorAxisHistory, testParticleCaseData->centralBodyGravitationalParameter ); // Compute reduced longitude history (data is reduced to only the epoch windows). DoubleKeyDoubleValueMap reducedLongitudeHistory = reduceLongitudeHistory( longitudeHistory, iteratorRandomWalkInputTable->observationPeriodStartEpoch, epochWindowSpacing, randomWalkRun->epochWindowSize, randomWalkRun->numberOfEpochWindows ); // Set input data for simple linear regression. SimpleLinearRegression longitudeHistoryRegression( reducedLongitudeHistory ); // Compute linear fit. longitudeHistoryRegression.computeFit( ); // Store longitude residuals history. DoubleKeyDoubleValueMap longitudeResidualsHistory; // Generate longitude history residuals by subtracting linear fit from data. for ( DoubleKeyDoubleValueMap::iterator iteratorReducedLongitudeHistory = reducedLongitudeHistory.begin( ); iteratorReducedLongitudeHistory != reducedLongitudeHistory.end( ); iteratorReducedLongitudeHistory++ ) { longitudeResidualsHistory[ iteratorReducedLongitudeHistory->first ] = iteratorReducedLongitudeHistory->second - longitudeHistoryRegression.getCoefficientOfConstantTerm( ) - longitudeHistoryRegression.getCoefficientOfLinearTerm( ) * iteratorReducedLongitudeHistory->first; } // Loop over observation period and compute average longitude residuals per epoch window. for ( int windowNumber = 0; windowNumber < randomWalkRun->numberOfEpochWindows; windowNumber++ ) { const double epochWindowCenter = iteratorRandomWalkInputTable->observationPeriodStartEpoch + windowNumber * epochWindowSpacing; averageLongitudeResiduals[ epochWindowCenter ] = computeStepFunctionWindowAverage( longitudeResidualsHistory, epochWindowCenter - 0.5 * randomWalkRun->epochWindowSize, epochWindowCenter + 0.5 * randomWalkRun->epochWindowSize ); } // Compute average longitude residual during propagation history. double sumLongitudeResiduals = 0.0; for ( DoubleKeyDoubleValueMap::iterator iteratorAverageLongitudeResiduals = averageLongitudeResiduals.begin( ); iteratorAverageLongitudeResiduals != averageLongitudeResiduals.end( ); iteratorAverageLongitudeResiduals++ ) { sumLongitudeResiduals += iteratorAverageLongitudeResiduals->second; } averageLongitudeResidual = sumLongitudeResiduals / randomWalkRun->numberOfEpochWindows; // Compute maximum longitude residual change during propagation history. maximumLongitudeResidualChange = ( max_element( averageLongitudeResiduals.begin( ), averageLongitudeResiduals.end( ), CompareDoubleKeyDoubleValueMapValues( ) ) )->second - ( min_element( averageLongitudeResiduals.begin( ), averageLongitudeResiduals.end( ), CompareDoubleKeyDoubleValueMapValues( ) ) )->second; // Check if output mode is set to "FILE". // If so, open output file and write header content. if ( iequals( outputMode, "FILE" ) ) { ostringstream longitudeHistoryFilename; longitudeHistoryFilename << "randomWalkSimulation" << iteratorRandomWalkInputTable->randomWalkSimulationId << "_longitudeHistory.csv"; ostringstream longitudeHistoryFileHeader; longitudeHistoryFileHeader << "epoch,longitude" << endl; longitudeHistoryFileHeader << "# [s],[rad]" << endl; writeDataMapToTextFile( longitudeHistory, longitudeHistoryFilename.str( ), fileOutputDirectory, longitudeHistoryFileHeader.str( ), numeric_limits< double >::digits10, numeric_limits< double >::digits10, "," ); ostringstream reducedLongitudeHistoryFilename; reducedLongitudeHistoryFilename << "randomWalkSimulation" << iteratorRandomWalkInputTable->randomWalkSimulationId << "_reducedLongitudeHistory.csv"; ostringstream reducedLongitudeHistoryFileHeader; reducedLongitudeHistoryFileHeader << "epoch,longitude" << endl; reducedLongitudeHistoryFileHeader << "# [s],[rad]" << endl; writeDataMapToTextFile( reducedLongitudeHistory, reducedLongitudeHistoryFilename.str( ), fileOutputDirectory, reducedLongitudeHistoryFileHeader.str( ), numeric_limits< double >::digits10, numeric_limits< double >::digits10, "," ); ostringstream longitudeResidualsFilename; longitudeResidualsFilename << "randomWalkSimulation" << iteratorRandomWalkInputTable->randomWalkSimulationId << "_longitudeResiduals.csv"; ostringstream longitudeResidualsFileHeader; longitudeResidualsFileHeader << "epoch,longitudeResidual" << endl; longitudeResidualsFileHeader << "# [s],[rad]" << endl; writeDataMapToTextFile( longitudeResidualsHistory, longitudeResidualsFilename.str( ), fileOutputDirectory, longitudeResidualsFileHeader.str( ), numeric_limits< double >::digits10, numeric_limits< double >::digits10, "," ); } } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Compute average eccentricity and maximum eccentricity change in observation window. // Declare average eccentricity in observation period [-]. double averageEccentricity = TUDAT_NAN; // Declare maximum eccentricity change in observation period [-]. double maximumEccentricityChange = TUDAT_NAN; // Declare map of average eccentricities per window [-]. DoubleKeyDoubleValueMap averageEccentricities; { // Populate temporary map with epochs and eccentricities. DoubleKeyDoubleValueMap eccentricityHistory; for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements = keplerianActionElementsHistory.begin( ); iteratorKeplerianActionElements != keplerianActionElementsHistory.end( ); iteratorKeplerianActionElements++ ) { eccentricityHistory[ iteratorKeplerianActionElements->first ] = iteratorKeplerianActionElements->second( eccentricityIndex ); } // Loop over observation period and compute average eccentricities per epoch window. for ( int windowNumber = 0; windowNumber < randomWalkRun->numberOfEpochWindows; windowNumber++ ) { const double epochWindowCenter = iteratorRandomWalkInputTable->observationPeriodStartEpoch + windowNumber * epochWindowSpacing; averageEccentricities[ epochWindowCenter ] = computeStepFunctionWindowAverage( eccentricityHistory, epochWindowCenter - 0.5 * randomWalkRun->epochWindowSize, epochWindowCenter + 0.5 * randomWalkRun->epochWindowSize ); } // Compute average eccentricity during propagation history. double sumEccentricities = 0.0; for ( DoubleKeyDoubleValueMap::iterator iteratorAverageEccentricities = averageEccentricities.begin( ); iteratorAverageEccentricities != averageEccentricities.end( ); iteratorAverageEccentricities++ ) { sumEccentricities += iteratorAverageEccentricities->second; } averageEccentricity = sumEccentricities / randomWalkRun->numberOfEpochWindows; // Compute maximum eccentricity change during propagation history. maximumEccentricityChange = ( max_element( averageEccentricities.begin( ), averageEccentricities.end( ), CompareDoubleKeyDoubleValueMapValues( ) ) )->second - ( min_element( averageEccentricities.begin( ), averageEccentricities.end( ), CompareDoubleKeyDoubleValueMapValues( ) ) )->second; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Compute average inclination and maximum inclination change in observation window. // Declare average inclination in observation period [rad]. double averageInclination = TUDAT_NAN; // Declare maximum inclination change in observation period [rad]. double maximumInclinationChange = TUDAT_NAN; // Declare map of average inclinations per window [rad]. DoubleKeyDoubleValueMap averageInclinations; { // Populate temporary map with epochs and inclinations. DoubleKeyDoubleValueMap inclinationHistory; for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements = keplerianActionElementsHistory.begin( ); iteratorKeplerianActionElements != keplerianActionElementsHistory.end( ); iteratorKeplerianActionElements++ ) { inclinationHistory[ iteratorKeplerianActionElements->first ] = iteratorKeplerianActionElements->second( inclinationIndex ); } // Loop over observation period and compute average inclinations per epoch window. for ( int windowNumber = 0; windowNumber < randomWalkRun->numberOfEpochWindows; windowNumber++ ) { const double epochWindowCenter = iteratorRandomWalkInputTable->observationPeriodStartEpoch + windowNumber * epochWindowSpacing; averageInclinations[ epochWindowCenter ] = computeStepFunctionWindowAverage( inclinationHistory, epochWindowCenter - randomWalkRun->epochWindowSize * 0.5, epochWindowCenter + randomWalkRun->epochWindowSize * 0.5 ); } // Compute average inclination during propagation history. double sumInclinations = 0.0; for ( DoubleKeyDoubleValueMap::iterator iteratorAverageInclinations = averageInclinations.begin( ); iteratorAverageInclinations != averageInclinations.end( ); iteratorAverageInclinations++ ) { sumInclinations += iteratorAverageInclinations->second; } averageInclination = sumInclinations / randomWalkRun->numberOfEpochWindows; // Compute maximum inclination change during propagation history. maximumInclinationChange = ( max_element( averageInclinations.begin( ), averageInclinations.end( ), CompareDoubleKeyDoubleValueMapValues( ) ) )->second - ( min_element( averageInclinations.begin( ), averageInclinations.end( ), CompareDoubleKeyDoubleValueMapValues( ) ) )->second; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Write epoch-windoow average values to file. // Check if output mode is set to "FILE". // If so, open output file and write header content. if ( iequals( outputMode, "FILE" ) ) { // Declare file handler. ofstream epochWindowAveragesFile; ostringstream epochWindowAveragesFilename; epochWindowAveragesFilename << fileOutputDirectory << "randomWalkRun" << iteratorRandomWalkInputTable->randomWalkSimulationId << "_epochWindowAverages.csv"; epochWindowAveragesFile.open( epochWindowAveragesFilename.str( ).c_str( ) ); epochWindowAveragesFile << "epoch,longitudeResidual,eccentricity,inclination" << endl; epochWindowAveragesFile << "# [s],[rad],[-],[rad]" << endl; // Loop through epoch-window averages and write data to file. DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageLongitudeResiduals = averageLongitudeResiduals.begin( ); DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageEccentricities = averageEccentricities.begin( ); DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageInclinations = averageInclinations.begin( ); for ( int i = 0; i < randomWalkRun->numberOfEpochWindows; i++ ) { epochWindowAveragesFile << setprecision( numeric_limits< double >::digits10 ) << iteratorEpochWindowAverageLongitudeResiduals->first << "," << iteratorEpochWindowAverageLongitudeResiduals->second << "," << iteratorEpochWindowAverageEccentricities->second << "," << iteratorEpochWindowAverageInclinations->second << endl; iteratorEpochWindowAverageLongitudeResiduals++; iteratorEpochWindowAverageEccentricities++; iteratorEpochWindowAverageInclinations++; } // Close file handler. epochWindowAveragesFile.close( ); } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Write random walk output to database. To avoid locking of the database, this section is // thread-critical, so will be executed one-by-one by multiple threads. // Check if output mode is set to "DATABASE". if ( iequals( outputMode, "DATABASE" ) ) { #pragma omp critical( databaseOperations ) { // Populate output table in database. populateRandomWalkOutputTable( databasePath, iteratorRandomWalkInputTable->randomWalkSimulationId, averageLongitudeResidual, maximumLongitudeResidualChange, averageEccentricity, maximumEccentricityChange, averageInclination, maximumInclinationChange, randomWalkOutputTableName, randomWalkInputTableName ); } } ///////////////////////////////////////////////////////////////// } // simulation for-loop /////////////////////////////////////////////////////////////////// }
bool absLess(int a, int b) { return abs(a) < abs(b); } BEGIN_TEST(NonModifyingAlgorithm, MinMaxElem, @); deque<int> con; insertElements(con, 1, 10); insertElements(con, -5, 5); printContainer(con); // con: 1 2 3 4 5 6 7 8 9 10 -5 -4 -3 -2 -1 0 1 2 3 4 5 auto minPos = min_element(con.begin(), con.end()); EXPECT_EQ(-5, *minPos); auto maxPos = max_element(con.begin(), con.end()); EXPECT_EQ(10, *maxPos); auto absMinPos = min_element(con.begin(), con.end(), absLess); EXPECT_EQ(0, *absMinPos); auto absMaxPos = max_element(con.begin(), con.end(), absLess); EXPECT_EQ(10, *absMaxPos); END_TEST; BEGIN_TEST(NonModifyingAlgorithm, Find, @); list<int> con; insertElements(con, 0, 10); insertElements(con, 0, 5);
/** * \brief Given a set of observations, fit this mixture using * expectation maximization */ void DistributionMixtureModel::estimateParamsEM(const vector<double>& obs, bool verbose) { bool debug = false; double oldLogLike = 0; bool first = true; bool done = false; size_t numIter = 0; size_t K = this->numberOfComponents(); // only one component? easy peasy.. if (K == 1) { this->ds[0]->estimateParams(obs, verbose); this->mixing[0] = 1; return; } // fail if there are more components in this mixture than there are // distinct observation values -- we can't fit that! set<double> unique(obs.begin(), obs.end()); if (obs.size() < this->ds.size()) { stringstream s; s << "cannot fit mixture model with " << this->ds.size() << " using only " << obs.size() << " data points!"; throw MixtureModelException(s.str().c_str()); } // make an initial random guess for (size_t k=0; k<K; k++) this->ds[k]->randomise(); if (verbose) cout << endl << "initial mixture starting point: " << this->toString() << endl; while (!done) { // expectation step -- compute weights given current params vector<vector<double> > w; for (size_t i = 0; i < obs.size(); i++) { // calculate z's for this i vector<double> z; for (size_t k = 0; k<K; k++) { z.push_back(log(this->mixing[k]) + this->ds[k]->loglikelihood(obs[i])); } // find max z and denominator for w double m = *max_element(z.begin(), z.end()); double d = 0; for (size_t k=0; k<K; k++) { d += exp(z[k] - m); } // calc weights for each component vector<double> wi; for (size_t k = 0; k<K; k++) { wi.push_back(exp(z[k] - m) / d); } w.push_back(wi); } if (debug) { for (size_t k = 0; k<K; k++) { for (size_t i = 0; i < obs.size(); i++) { cout << w[i][k] << ", " << this->ds[k]->loglikelihood(obs[i]) << " (" << obs[i] << "," << this->ds[k]->getParams()[0] << "," << this->ds[k]->getParams()[1] << ") " << ", "; } cout << endl; } } // maximisation step -- update model parameters mixing.clear(); for (size_t k=0; k<K; k++) { // update kth component vector<double> wk; for (size_t i = 0; i < obs.size(); i++) wk.push_back(w[i][k]); this->ds[k]->estimateParams(obs, wk); // update mixing parameter for kth component double sum = 0; for (size_t i = 0; i < obs.size(); i++) sum += w[i][k]; mixing.push_back(sum / obs.size()); } if (debug) cout << "after maximisation step, model is: " << this->toString() << endl; // set a lower bound on mixing params for (size_t k=0; k<K; k++) { if (this->mixing[k] < this->mixingLowerBound) this->mixing[k] = this->mixingLowerBound; } double total = 0; for (size_t i = 0; i < this->mixing.size(); i++) total += this->mixing[i]; for (size_t k = 0; k<K; k++) this->mixing[k] = this->mixing[k] / total; // finished because likelihood is stable? double newLogLike = this->loglikelihood(obs); if (verbose) { cout << this->toString() << endl; cout << "new loglike: " << newLogLike << " old loglike: " << oldLogLike << endl; } if ((!first) && (fabs(newLogLike - oldLogLike) < this->stoppingEM)) done = true; first = false; oldLogLike = newLogLike; // finished because we're giving up? numIter++; if (numIter >= this->emMaxIter) done = true; } }