/** * Execute any reports that have the model_state * specified as their execution state * * @param model_state The state the model has just finished */ void Manager::Execute(State::Type model_state) { LOG_TRACE(); RunMode::Type run_mode = model_->run_mode(); bool tabular = model_->global_configuration().print_tabular(); LOG_FINE() << "Checking " << state_reports_[model_state].size() << " reports"; for(auto report : state_reports_[model_state]) { if ( (RunMode::Type)(report->run_mode() & run_mode) == run_mode) { if (tabular) report->ExecuteTabular(); else report->Execute(); } else LOG_FINE() << "Skipping report: " << report->label() << " because run mode is incorrect"; } }
void SumToOne::DoBuild() { LOG_TRACE(); for (auto& estimate_label : estimate_labels_) { Estimate* estimate = model_->managers().estimate()->GetEstimateByLabel(estimate_label); if (estimate == nullptr) { LOG_ERROR_P(PARAM_ESTIMATE_LABELS) << "Estimate " << estimate_label << " could not be found. Have you defined it?"; return; } else { LOG_FINE() << "transform with objective = " << transform_with_jacobian_ << " estimate transform " << estimate->transform_for_objective() << " together = " << !transform_with_jacobian_ && !estimate->transform_for_objective(); if (!transform_with_jacobian_ && !estimate->transform_for_objective()) { LOG_ERROR_P(PARAM_LABEL) << "You have specified a transformation that does not contribute a jacobian, and the prior parameters do not refer to the transformed estimate, in the @estimate" << estimate_label_ << ". This is not advised, and may cause bias estimation. Please address the user manual if you need help"; } if (estimate->transform_with_jacobian_is_defined()) { if (transform_with_jacobian_ != estimate->transform_with_jacobian()) { LOG_ERROR_P(PARAM_LABEL) << "This parameter is not consistent with the equivalent parameter in the @estimate block " << estimate_label_ << ". please make sure these are both true or both false."; } } estimates_.push_back(estimate); } } // Validate that the parameters sum to one. Double total = 0.0; for (auto& estimate : estimates_) { LOG_FINEST() << "transformation value = " << estimate->value(); total += estimate->value(); } if (total != 1.0) LOG_ERROR_P(PARAM_ESTIMATE_LABELS) << "The estiamtes you supplied to not sum to 1.0, they sum to " << total << ", please check initial values of these parameters"; // Check that the bounds are sensible if (parameters_.Get(PARAM_UPPER_BOUND)->has_been_defined() & parameters_.Get(PARAM_LOWER_BOUND)->has_been_defined()) { for (unsigned i = 0; i < estimates_.size(); ++i) { if (estimates_[i]->lower_bound() < 0.0 || estimates_[i]->lower_bound() > 1.0) LOG_ERROR_P(PARAM_LOWER_BOUND) << "You cannot specify a lower bound less than 0 and greater than 1.0"; if (estimates_[i]->upper_bound() < 0.0 || estimates_[i]->upper_bound() > 1.0) LOG_ERROR_P(PARAM_UPPER_BOUND) << "You cannot specify a upper bound less than 0 and greater than 1.0"; } } LOG_MEDIUM() << "total = " << total; // Turn off the last estimate LOG_FINE() << "Turning off parameter, this won't be estimated, and will be an outcome of other parameters " << estimates_[estimates_.size() - 1]->parameter() << " in the estimation"; estimates_[estimates_.size() - 1]->set_estimated(false); LOG_MEDIUM() << "flagged estimated = " << estimates_[estimates_.size() - 1]->estimated(); }
void Project::RestoreOriginalValue(unsigned year) { LOG_TRACE(); if (addressable_ != nullptr) { LOG_FINE() << "Setting original value to: " << original_value_; (this->*DoUpdateFunc_)(original_value_); } }
/** * Build our time step */ void TimeStep::Build() { // Get the pointers to our processes processes::Manager& process_manager = *model_->managers().process(); for (string process_name : process_names_) { Process* process = process_manager.GetProcess(process_name); if (!process) { LOG_ERROR_P(PARAM_PROCESSES) << ": process " << process_name << " does not exist. Have you defined it?"; } else processes_.push_back(process); } LOG_FINE() << "Time step " << label_ << " has " << processes_.size() << " processes"; /** * Find the range of our mortality block. This block encompasses the * first continuous collection of mortality processes within the time * step. */ mortality_block_.first = processes_.size(); mortality_block_.second = processes_.size() - 1; bool finished_mortality_block = false; for (unsigned i = 0; i < processes_.size(); ++i) { if (processes_[i]->process_type() == ProcessType::kMortality && !finished_mortality_block) { mortality_block_.first = mortality_block_.first == processes_.size() ? i : mortality_block_.first; mortality_block_.second = i; } else if (processes_[i]->process_type() == ProcessType::kMortality && finished_mortality_block) { LOG_FATAL() << "Mortality processes within a time step need to be consecutive (i.e. a single mortality block)"; } else if (mortality_block_.first != processes_.size()) finished_mortality_block = true; } mortality_block_.second = mortality_block_.first == processes_.size() ? mortality_block_.first : mortality_block_.second; }
void CovarianceMatrix::DoExecute() { /* * This reports the Covariance, Correlation and Hessian matrix */ LOG_TRACE(); auto minimiser_ = model_->managers().minimiser()->active_minimiser(); covariance_matrix_ = minimiser_->covariance_matrix(); cache_ << "*" << label_ << " " << "(" << type_ << ")" << "\n"; cache_ << "Covariance_Matrix " << REPORT_R_MATRIX << "\n"; for (unsigned i = 0; i < covariance_matrix_.size1(); ++i) { for (unsigned j = 0; j < covariance_matrix_.size2(); ++j) cache_ << covariance_matrix_(i, j) << " "; cache_ << "\n"; } if (model_->run_mode() == RunMode::kMCMC) { auto mcmc_ = model_->managers().mcmc()->active_mcmc(); if (mcmc_->recalculate_covariance()) { cache_ << REPORT_END << "\n\n"; LOG_FINE() << "During the mcmc run you recalculated the the covariance matrix, so we will print the modified matrix at the end of the chain"; cache_ << "Modified_covariance_matrix " << REPORT_R_MATRIX << "\n"; auto covariance = mcmc_->covariance_matrix(); for (unsigned i = 0; i < covariance.size1(); ++i) { for (unsigned j = 0; j < covariance.size2() - 1; ++j) cache_ << covariance(i, j) << " "; cache_ << covariance(i, covariance.size2() - 1) << "\n"; } } } ready_for_writing_ = true; }
/** * @param current_year teh current year this method is calles * * This function will store all parameter values that we may want to overwrite at in projection years */ void Manager::StoreValues(unsigned current_year, unsigned start_year, unsigned final_year) { LOG_TRACE(); // iterate over all @project blocks for (auto project : objects_) { LOG_FINE() << "@Project: " << project->label(); project->StoreValue(current_year, start_year, final_year); } }
/** * This method can be called from the main thread to ensure * we wait for all reports to finish */ void Manager::WaitForReportsToFinish() { #ifndef TESTMODE waiting_ = true; LOG_FINE() << "Waiting for reports"; while(waiting_); #endif return; }
/** * Build our reports then * organise the reports stored in our * object list into different containers * based on their type. */ void Manager::Build() { LOG_FINEST() << "objects_.size(): " << objects_.size(); for (auto report : objects_) { report->Build(); if ((RunMode::Type)(report->run_mode() & RunMode::kInvalid) == RunMode::kInvalid) LOG_CODE_ERROR() << "Report: " << report->label() << " has not been properly configured to have a run mode"; if (report->model_state() != State::kExecute) { LOG_FINE() << "Adding report " << report->label() << " to state reports"; state_reports_[report->model_state()].push_back(report); } else { LOG_FINE() << "Adding report " << report->label() << " to time step reports"; time_step_reports_[report->time_step()].push_back(report); } } }
/** * Execute our DE Solver minimiser engine */ void DESolver::Execute() { estimates::Manager& estimate_manager = *model_->managers().estimate(); vector<double> lower_bounds; vector<double> upper_bounds; vector<double> start_values; model_->managers().estimate_transformation()->TransformEstimates(); vector<Estimate*> estimates = estimate_manager.GetIsEstimated(); for (Estimate* estimate : estimates) { if (!estimate->estimated()) continue; lower_bounds.push_back(estimate->lower_bound()); upper_bounds.push_back(estimate->upper_bound()); start_values.push_back(estimate->value()); if (estimate->value() < estimate->lower_bound()) { LOG_FATAL() << "When starting the DESolver minimiser the starting value (" << estimate->value() << ") for estimate " << estimate->parameter() << " was less than the lower bound (" << estimate->lower_bound() << ")"; } else if (estimate->value() > estimate->upper_bound()) { LOG_FATAL() << "When starting the DESolver minimiser the starting value (" << estimate->value() << ") for estimate " << estimate->parameter() << " was greater than the upper bound (" << estimate->upper_bound() << ")"; } } // Setup Engine desolver::CallBack solver = desolver::CallBack(model_, start_values.size(), population_size_, tolerance_); solver.Setup(start_values, lower_bounds, upper_bounds, kBest1Exp, difference_scale_, crossover_probability_); // Solver if (solver.Solve(max_generations_)) { result_ = MinimiserResult::kSuccess; LOG_FINE() << "DE Solver has successfully converged"; } else { result_ = MinimiserResult::kError; LOG_FINE() << "DE Solver has failed to converge"; } model_->managers().estimate_transformation()->RestoreEstimates(); }
/** * Attempt to open our configuration file * * @param file_name The name of the file to open * @return true on success, false on failure */ bool File::OpenFile(string file_name) { LOG_TRACE(); file_name_ = file_name; LOG_FINE() << "Opening file: " << file_name; file_.open(file_name_.c_str()); if (file_.fail() || !file_.is_open()) return false; return true; }
/** * This will restore values provided by the minimiser that need to be restored for use in the annual cycle */ void SumToOne::DoRestore() { LOG_TRACE(); // Create zk Double total = 0.0; for (unsigned i = 0; i < (estimates_.size() - 1); ++i) { total += estimates_[i]-> value(); } Double new_value = 1.0 - total; LOG_FINE() << "Setting value to " << new_value << " for parameter = " << estimates_[estimates_.size() - 1]->parameter(); estimates_[estimates_.size() - 1]->set_value(new_value); }
TimeStep* Manager::GetTimeStep(const string& label) const { LOG_FINE() << "label: " << label; TimeStep* result = nullptr; for (auto time_step : objects_) { if (time_step->label() == label) { result = time_step; break; } } return result; }
/** * This method collapses the Numbers at length by age matrix to numbers at age for a category */ void Category::CollapseAgeLengthDataToLength() { LOG_TRACE(); if (age_length_matrix_.size() == 0) LOG_CODE_ERROR() << "if (age_length_matrix_.size() == 0)"; LOG_FINE() << "age_length_matrix_.size(): " << age_length_matrix_.size(); LOG_FINE() << "age_length_matrix_[0].size(): " << age_length_matrix_[0].size(); length_data_.assign(model_->length_bins().size(), 0.0); for (unsigned i = 0; i < age_length_matrix_.size(); ++i) { for (unsigned j = 0; j < age_length_matrix_[i].size(); ++j) { if (j >= length_data_.size()) LOG_CODE_ERROR() << "j >= length_data_.size()"; length_data_[j] += age_length_matrix_[i][j]; } } for (unsigned i = 0; i < length_data_.size(); ++i) LOG_FINEST() << "length_data_[" << i << "]: " << length_data_[i]; }
/** * Execute this report */ void Project::DoExecute() { LOG_FINE() <<" printing report " << label_ << " of type " << project_->type(); map<unsigned,Double>& values = project_->projected_parameters(); cache_ << "*"<< type_ << "[" << label_ << "]" << "\n"; cache_ << "project: " << project_label_ << "\n"; cache_ << "values " << REPORT_R_VECTOR <<"\n"; for(auto value : values) { cache_ << value.first << " " << value.second << "\n"; } ready_for_writing_ = true; }
/** * Execute all of the timesteps * for the current year. */ void Manager::Execute(unsigned year) { LOG_TRACE(); reports::Manager& report_manager = *model_->managers().report(); for (current_time_step_ = 0; current_time_step_ < ordered_time_steps_.size(); ++current_time_step_) { LOG_FINE() << "Current Time Step: " << current_time_step_; ordered_time_steps_[current_time_step_]->Execute(year); report_manager.Execute(year, ordered_time_steps_[current_time_step_]->label()); } // reset this for age sizes current_time_step_ = 0; }
std::string IFStreamFile::readAll() { ENFORCE(m_ifs.is_open(), "File must be opened before reading it!"); LOG_DEBUG("Read all data from file: ", getName()); std::string line; std::string data; while(getline(m_ifs, line)) { LOG_FINE("line read: '", line, "'"); data.append(line + "\n"); } return data; }
/** * Simulate observed values * * @param comparisons A collection of comparisons passed by the observation */ void BinomialApprox::SimulateObserved(map<unsigned, vector<observations::Comparison> >& comparisons) { utilities::RandomNumberGenerator& rng = utilities::RandomNumberGenerator::Instance(); Double error_value = 0.0; auto iterator = comparisons.begin(); for (; iterator != comparisons.end(); ++iterator) { LOG_FINE() << "Simulating values for year: " << iterator->first; for (observations::Comparison& comparison : iterator->second) { error_value = ceil(AS_DOUBLE(AdjustErrorValue(comparison.process_error_, comparison.error_value_))); if (comparison.expected_ <= 0.0 || error_value <= 0.0) comparison.observed_ = 0.0; else comparison.observed_ = rng.binomial(AS_DOUBLE(comparison.expected_), AS_DOUBLE(error_value)) / error_value; } } }
/** * Execute the minimiser to solve the model */ void GammaDiff::Execute() { LOG_TRACE(); // Variables LOG_FINE() << "model_: " << model_; gammadiff::CallBack call_back(model_); estimates::Manager* estimate_manager = model_->managers().estimate(); LOG_FINE() << "estimate_manager: " << estimate_manager; vector<double> lower_bounds; vector<double> upper_bounds; vector<double> start_values; model_->managers().estimate_transformation()->TransformEstimates(); vector<Estimate*> estimates = estimate_manager->GetIsEstimated(); LOG_FINE() << "estimates.size(): " << estimates.size(); for (Estimate* estimate : estimates) { if (!estimate->estimated()) continue; LOG_FINE() << "Estimate: " << estimate; LOG_FINE() << "transformed value: " << estimate->value(); LOG_FINE() << "Parameter: " << estimate->parameter(); lower_bounds.push_back((double)estimate->lower_bound()); upper_bounds.push_back((double)estimate->upper_bound()); start_values.push_back((double)estimate->value()); if (estimate->value() < estimate->lower_bound()) { LOG_FATAL() << "When starting the GammDiff numerical_differences minimiser the starting value (" << estimate->value() << ") for estimate " << estimate->parameter() << " was less than the lower bound (" << estimate->lower_bound() << ")"; } else if (estimate->value() > estimate->upper_bound()) { LOG_FATAL() << "When starting the GammDiff numerical_differences minimiser the starting value (" << estimate->value() << ") for estimate " << estimate->parameter() << " was greater than the upper bound (" << estimate->upper_bound() << ")"; } } LOG_FINE() << "Launching minimiser"; int status = 0; gammadiff::Engine clGammaDiff; clGammaDiff.optimise_finite_differences(call_back, start_values, lower_bounds, upper_bounds, status, max_iterations_, max_evaluations_, gradient_tolerance_, hessian_,1,step_size_); model_->managers().estimate_transformation()->RestoreEstimates(); }
/** * Build */ void Manager::Build(Model* model) { LOG_TRACE(); if (model->run_mode() == RunMode::kProjection) { bool ycs_values_exist = false; for (auto project : objects_) { LOG_FINE() << "Building Project: " << project->label(); project->Build(); if (project->estimable_parameter() == PARAM_YCS_VALUES) ycs_values_exist = true; } if (!ycs_values_exist) { for (auto process : model->managers().process()->objects()) { if (process->type() == PARAM_RECRUITMENT_BEVERTON_HOLT) LOG_ERROR() << process->location() << " process " << process->label() << " does not contain a @project for ycs_values, but you are running in projection mode"; } } } }
/** * Execute our maturation rate process. */ void TransitionCategory::DoExecute() { LOG_TRACE(); auto from_iter = from_partition_.begin(); auto to_iter = to_partition_.begin(); Double amount = 0.0; LOG_FINEST() << "transition_rates_.size(): " << transition_rates_.size() << "; from_partition_.size(): " << from_partition_.size() << "; to_partition_.size(): " << to_partition_.size(); if (from_partition_.size() != to_partition_.size()) { LOG_FATAL() << "The list of categories for the Transition Category process are not of equal size in year " << model_->current_year() << ". We have " << from_partition_.size() << " and " << to_partition_.size() << " categories to transition between"; } if (transition_rates_.size() != from_partition_.size()) { LOG_FINE() << "Re-building the transition rates because the partition size has changed"; transition_rates_.resize(from_partition_.size()); for (unsigned i = 0; i < transition_rates_.size(); ++i) { Double proportion = proportions_.size() > 1 ? proportions_[i] : proportions_[0]; unsigned min_age = (*from_iter)->min_age_; for (unsigned j = 0; j < (*from_iter)->data_.size(); ++j) { transition_rates_[i].push_back(proportion * selectivities_[i]->GetResult(min_age + j, (*from_iter)->age_length_)); if (selectivities_[i]->GetResult(min_age + j, (*from_iter)->age_length_) > 1.0) LOG_ERROR() << " Selectivity result is greater than 1.0, check selectivity"; } } } for (unsigned i = 0; from_iter != from_partition_.end() && to_iter != to_partition_.end(); ++from_iter, ++to_iter, ++i) { for (unsigned offset = 0; offset < (*from_iter)->data_.size(); ++offset) { amount = transition_rates_[i][offset] * (*from_iter)->data_[offset]; (*from_iter)->data_[offset] -= amount; (*to_iter)->data_[offset] += amount; if ((*from_iter)->data_[offset] < 0.0) LOG_FATAL() << "Maturation rate caused a negative partition if ((*from_iter)->data_[offset] < 0.0) "; } } }
void Linear::DoReset() { bool current_year = model_->current_year() == years_[0]; unsigned diff = model_->current_year() - years_[0]; LOG_FINE() << "diff unsigned = " << diff; Double years_since_first_year = (Double)model_->current_year() - (Double)years_[0]; LOG_FINE() << "diff from start of year = " << years_since_first_year; LOG_FINE() << " did we make it past this if statement " << current_year; if (current_year) { // First year don't make a change LOG_FINE() << "Setting Value to: " << intercept_; parameter_by_year_[model_->current_year()] = intercept_; } else { // Add a linear trend parameter_by_year_[model_->current_year()] = intercept_ + years_since_first_year * slope_; //value_ = model_->objects().GetEstimable(parameter_, error); LOG_FINE() << "value = " << parameter_by_year_[model_->current_year()]; LOG_FINE() << "value after deviate of " << slope_ << " = " << parameter_by_year_[model_->current_year()] << " for year " << model_->current_year(); LOG_FINE() << "Setting Value to: " << parameter_by_year_[model_->current_year()]; } }
void ProcessRemovalsByLength::Execute() { LOG_TRACE(); /** * Verify our cached partition and partition sizes are correct */ // auto categories = model_->categories(); unsigned year = model_->current_year(); unsigned year_index = year - model_->start_year(); unsigned time_step = model_->managers().time_step()->current_time_step(); auto cached_partition_iter = cached_partition_->Begin(); auto partition_iter = partition_->Begin(); // vector<vector<partition::Category> > map<unsigned, map<string, map<string, vector<Double>>>> &Removals_at_age = mortality_instantaneous_->catch_at(); /** * Loop through the provided categories. Each provided category (combination) will have a list of observations * with it. We need to build a vector of proportions for each length using that combination and then * compare it to the observations. */ for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter, ++cached_partition_iter) { LOG_FINEST() << "category: " << category_labels_[category_offset]; Double start_value = 0.0; Double end_value = 0.0; Double number_at_age = 0.0; // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; vector<Double> expected_values(number_bins_, 0.0); vector<Double> numbers_at_length; vector<vector<Double>> age_length_matrix; /** * Loop through the 2 combined categories building up the * expected proportions values. */ auto category_iter = partition_iter->begin(); auto cached_category_iter = cached_partition_iter->begin(); for (; category_iter != partition_iter->end(); ++cached_category_iter, ++category_iter) { // AgeLength* age_length = categories->age_length((*category_iter)->name_); // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; age_length_matrix.resize((*category_iter)->data_.size()); vector<Double> age_frequencies(length_bins_.size(), 0.0); const auto& age_length_proportions = model_->partition().age_length_proportions((*category_iter)->name_)[year_index][time_step]; for (unsigned data_offset = 0; data_offset < (*category_iter)->data_.size(); ++data_offset) { unsigned age = ((*category_iter)->min_age_ + data_offset); // Calculate the age structure removed from the fishing process number_at_age = Removals_at_age[year][method_][(*category_iter)->name_][data_offset]; LOG_FINEST() << "Numbers at age = " << age << " = " << number_at_age << " start value : " << start_value << " end value : " << end_value; // Implement an algorithm similar to DoAgeLengthConversion() to convert numbers at age to numbers at length // This is different to DoAgeLengthConversion as this number is now not related to the partition // Double mu= (*category_iter)->mean_length_by_time_step_age_[time_step][age]; // LOG_FINEST() << "mean = " << mu << " cv = " << age_length->cv(year, time_step, age) << " distribution = " << age_length->distribution_label() << " and length plus group = " << length_plus_; // age_length->CummulativeNormal(mu, age_length->cv(year, time_step, age), age_frequencies, length_bins_, length_plus_); // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; age_length_matrix[data_offset].resize(number_bins_); // Loop through the length bins and multiple the partition of the current age to go from // length frequencies to age length numbers for (unsigned j = 0; j < number_bins_; ++j) { age_length_matrix[data_offset][j] = number_at_age * age_length_proportions[data_offset][j]; LOG_FINEST() << "The proportion of fish in length bin : " << length_bins_[j] << " = " << age_frequencies[j]; } } if (age_length_matrix.size() == 0) LOG_CODE_ERROR()<< "if (age_length_matrix_.size() == 0)"; numbers_at_length.assign(age_length_matrix[0].size(), 0.0); for (unsigned i = 0; i < age_length_matrix.size(); ++i) { for (unsigned j = 0; j < age_length_matrix[i].size(); ++j) { numbers_at_length[j] += age_length_matrix[i][j]; } } for (unsigned length_offset = 0; length_offset < number_bins_; ++length_offset) { LOG_FINEST() << " numbers for length bin : " << length_bins_[length_offset] << " = " << numbers_at_length[length_offset]; expected_values[length_offset] += numbers_at_length[length_offset]; LOG_FINE() << "----------"; LOG_FINE() << "Category: " << (*category_iter)->name_ << " at length " << length_bins_[length_offset]; LOG_FINE() << "start_value: " << start_value << "; end_value: " << end_value << "; final_value: " << numbers_at_length[length_offset]; LOG_FINE() << "expected_value becomes: " << expected_values[length_offset]; } } if (expected_values.size() != proportions_[model_->current_year()][category_labels_[category_offset]].size()) LOG_CODE_ERROR()<< "expected_values.size(" << expected_values.size() << ") != proportions_[category_offset].size(" << proportions_[model_->current_year()][category_labels_[category_offset]].size() << ")"; /** * save our comparisons so we can use them to generate the score from the likelihoods later */ for (unsigned i = 0; i < expected_values.size(); ++i) { SaveComparison(category_labels_[category_offset], 0, length_bins_[i], expected_values[i], proportions_[model_->current_year()][category_labels_[category_offset]][i], process_errors_by_year_[model_->current_year()], error_values_[model_->current_year()][category_labels_[category_offset]][i], 0.0, delta_, 0.0); } } }
void Constant::DoUpdate() { LOG_FINE() << "Setting Value to: " << parameter_by_year_[model_->current_year()]; (this->*update_function_)(parameter_by_year_[model_->current_year()]); }
/** * Execute Cinitial this code follows from the original CASAL algorithm */ void Cinitial::Execute() { LOG_TRACE(); map<string, vector<Double>> category_by_age_total; auto partition_iter = partition_->Begin(); for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter) { category_by_age_total[category_labels_[category_offset]].assign((max_age_ - min_age_ + 1), 0.0); /** * Loop through the combined categories building up the total abundance for each category label */ auto category_iter = partition_iter->begin(); for (; category_iter != partition_iter->end(); ++category_iter) { for (unsigned data_offset = 0; data_offset < (max_age_ - min_age_ + 1); ++data_offset) { unsigned age_offset = (*category_iter)->min_age_ - min_age_; // if this category min_age occurs after model min age ignore current age if (data_offset < age_offset) continue; category_by_age_total[category_labels_[category_offset]][data_offset] += (*category_iter)->data_[data_offset - age_offset]; } } } LOG_TRACE(); // loop through the category_labels and calculate the cinitial factor, which is the n_ / col_sums map<string, vector<Double>> category_by_age_factor; for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset) { category_by_age_factor[category_labels_[category_offset]].assign((max_age_ - min_age_ + 1), 0.0); for (unsigned data_offset = 0; data_offset < (max_age_ - min_age_ + 1); ++data_offset) { if (category_by_age_total[category_labels_[category_offset]][data_offset] == 0.0) category_by_age_factor[category_labels_[category_offset]][data_offset] = 1.0; else { category_by_age_factor[category_labels_[category_offset]][data_offset] = n_[utilities::ToLowercase(category_labels_[category_offset])][data_offset] / category_by_age_total[category_labels_[category_offset]][data_offset]; } } } LOG_TRACE(); // Now loop through the combined categories multiplying each category by the factory // from the combined group it belongs to partition_iter = partition_->Begin(); for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter) { /** * Loop through the combined categories building up the total abundance for each category label */ auto category_iter = partition_iter->begin(); for (; category_iter != partition_iter->end(); ++category_iter) { for (unsigned data_offset = 0; data_offset < (max_age_ - min_age_ + 1); ++data_offset) { unsigned age_offset = (*category_iter)->min_age_ - min_age_; // if this category min_age occurs after model min age ignore this age if (data_offset < age_offset) continue; (*category_iter)->data_[data_offset - age_offset] *= category_by_age_factor[category_labels_[category_offset]][data_offset]; } } } // Build cache LOG_FINEST() << "finished calculating Cinitial"; cached_partition_->BuildCache(); // Execute the annual cycle for one year to calculate Cinitial timesteps::Manager* time_step_manager = model_->managers().time_step(); time_step_manager->ExecuteInitialisation(label_, 1); // Store that SSB value ssb_offset times in the Cintiial phase GetPhaseIndex LOG_FINE() << "derived_ptr_.size(): " << derived_ptr_.size(); for (auto derived_quantities : derived_ptr_) { vector<vector<Double>>& initialisation_values = derived_quantities->initialisation_values(); unsigned cinit_phase_index = model_->managers().initialisation_phase()->GetPhaseIndex(label_); LOG_FINE() << "initialisation_values size: " << initialisation_values.size(); LOG_FINE() << "ssb_offset: " << ssb_offset_; LOG_FINE() << "cinit_phase_index: " << cinit_phase_index; LOG_FINE() << "init_values[cinit_phase].size(): " << initialisation_values[cinit_phase_index].size(); for(unsigned i = 0; i < ssb_offset_; ++i) initialisation_values[cinit_phase_index].push_back(*initialisation_values[cinit_phase_index].rbegin()); } // set the partition back to Cinitial state auto cached_partition_iter = cached_partition_->Begin(); partition_iter = partition_->Begin(); for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter, ++cached_partition_iter) { auto category_iter = partition_iter->begin(); auto cached_category_iter = cached_partition_iter->begin(); for (; category_iter != partition_iter->end(); ++cached_category_iter, ++category_iter) { (*category_iter)->data_ = (*cached_category_iter).data_; } } }
/** * Default Constructor */ Manager::Manager() { LOG_FINE() << "TimeStep Manager Constructor"; }
void ProportionsMigrating::Execute() { LOG_TRACE(); /** * Verify our cached partition and partition sizes are correct */ auto cached_partition_iter = cached_partition_->Begin(); auto partition_iter = partition_->Begin(); // vector<vector<partition::Category> > /** * Loop through the provided categories. Each provided category (combination) will have a list of observations * with it. We need to build a vector of proportions for each age using that combination and then * compare it to the observations. */ LOG_FINEST() << "Number of categories " << category_labels_.size(); for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter, ++cached_partition_iter) { Double start_value = 0.0; Double end_value = 0.0; vector<Double> expected_values(age_spread_, 0.0); vector<Double> numbers_age_before((model_->age_spread() + 1), 0.0); vector<Double> numbers_age_after((model_->age_spread() + 1), 0.0); /** * Loop through the 2 combined categories building up the * expected proportions values. */ auto category_iter = partition_iter->begin(); auto cached_category_iter = cached_partition_iter->begin(); for (; category_iter != partition_iter->end(); ++cached_category_iter, ++category_iter) { for (unsigned data_offset = 0; data_offset < (*category_iter)->data_.size(); ++data_offset) { // We now need to loop through all ages to apply ageing misclassification matrix to account // for ages older than max_age_ that could be classified as an individual within the observation range unsigned age = ( (*category_iter)->min_age_ + data_offset); start_value = (*cached_category_iter).data_[data_offset]; end_value = (*category_iter)->data_[data_offset]; numbers_age_before[data_offset] += start_value; numbers_age_after[data_offset] += end_value; LOG_FINE() << "----------"; LOG_FINE() << "Category: " << (*category_iter)->name_ << " at age " << age; LOG_FINE() << "start_value: " << start_value << "; end_value: " << end_value; } } /* * Apply Ageing error on numbers at age before and after */ if (ageing_error_label_ != "") { vector<vector<Double>>& mis_matrix = ageing_error_->mis_matrix(); vector<Double> temp_before(numbers_age_before.size(), 0.0); vector<Double> temp_after(numbers_age_after.size(), 0.0); for (unsigned i = 0; i < mis_matrix.size(); ++i) { for (unsigned j = 0; j < mis_matrix[i].size(); ++j) { temp_before[j] += numbers_age_before[i] * mis_matrix[i][j]; temp_after[j] += numbers_age_after[i] * mis_matrix[i][j]; } } numbers_age_before = temp_before; numbers_age_after = temp_after; } /* * Now collapse the number_age into out expected values */ Double plus_before = 0, plus_after = 0; for (unsigned k = 0; k < numbers_age_before.size(); ++k) { // this is the difference between the unsigned age_offset = min_age_ - model_->min_age(); if (numbers_age_before[k] > 0) { if (k >= age_offset && (k - age_offset + min_age_) <= max_age_) { expected_values[k - age_offset] = (numbers_age_before[k] - numbers_age_after[k]) / numbers_age_before[k]; LOG_FINEST() << "Numbers before migration = " << numbers_age_before[k] << " numbers after migration = " << numbers_age_after[k] << " proportion migrated = " << expected_values[k - age_offset]; } if (((k - age_offset + min_age_) > max_age_) && age_plus_) { plus_before += numbers_age_before[k]; plus_after += numbers_age_after[k]; } } else { if (k >= age_offset && (k - age_offset + min_age_) <= max_age_) expected_values[k] = 0; if (((k - age_offset + min_age_) > max_age_) && age_plus_) { plus_before += 0; plus_after += 0; } } } LOG_FINEST() << "Plus group before migration = " << plus_before << " Plus group after migration = " << plus_after; if (age_plus_) expected_values[age_spread_ - 1] = (plus_before - plus_after) / plus_before; if (expected_values.size() != proportions_[model_->current_year()][category_labels_[category_offset]].size()) LOG_CODE_ERROR() << "expected_values.size(" << expected_values.size() << ") != proportions_[category_offset].size(" << proportions_[model_->current_year()][category_labels_[category_offset]].size() << ")"; /** * save our comparisons so we can use them to generate the score from the likelihoods later */ for (unsigned i = 0; i < expected_values.size(); ++i) { LOG_FINEST() << " Numbers at age " << min_age_ + i << " = " << expected_values[i]; SaveComparison(category_labels_[category_offset], min_age_ + i ,0.0 ,expected_values[i], proportions_[model_->current_year()][category_labels_[category_offset]][i], process_errors_by_year_[model_->current_year()], error_values_[model_->current_year()][category_labels_[category_offset]][i], delta_, 0.0); } } }