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);
    }
  }
}
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);
    }
  }
}
/**
 * Save the comparison that was done during an observation to the list of comparisons. Each comparison contributes part to a score
 * and we will need to know what those parts are when reporting.
 *
 * @param category The name of the comparison
 * @param age The age of the population being compared
 * @param expected The value generated by the model
 * @param observed The value passed in from the configuration file
 * @param error_value The error value for this comparison
 * @param score The amount of score for this comparison
 */
void Observation::SaveComparison(string category, Double expected, Double observed,
    Double process_error, Double error_value, Double adjusted_error, Double delta, Double score) {
  SaveComparison(category, 0, 0, expected, observed, process_error, error_value,adjusted_error, delta, score);
}