<commit_before>// Copyright (C) 2010 - 2016 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by <NAME>, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <cmath>

#include "copasi.h"

#include "CFitProblem.h"
#include "CFitItem.h"
#include "CFitTask.h"
#include "CExperimentSet.h"
#include "CExperiment.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "math/CMathContainer.h"
#include "model/CModel.h"
#include "report/CCopasiObjectReference.h"
#include "report/CKeyFactory.h"
#include "steadystate/CSteadyStateTask.h"
#include "trajectory/CTrajectoryTask.h"
#include "trajectory/CTrajectoryProblem.h"
#include "utilities/CProcessReport.h"
#include "utilities/CCopasiException.h"
#include "utilities/CAnnotatedMatrix.h"

#include "lapack/blaswrap.h"           //use blas
#include "lapack/lapackwrap.h"        //use CLAPACK

//  Default constructor
CFitProblem::CFitProblem(const CTaskEnum::Task & type,
                         const CCopasiContainer * pParent):
  COptProblem(type, pParent),
  mpParmSteadyStateCN(NULL),
  mpParmTimeCourseCN(NULL),
  mpExperimentSet(NULL),
  mpSteadyState(NULL),
  mpTrajectory(NULL),
  mExperimentValues(0, 0),
  mExperimentConstraints(0, 0),
  mExperimentDependentValues(0),
  mpCrossValidationSet(NULL),
  mCrossValidationValues(0, 0),
  mCrossValidationConstraints(0, 0),
  mCrossValidationDependentValues(0),
  mCrossValidationSolutionValue(mWorstValue),
  mCrossValidationRMS(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationSD(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationObjective(mWorstValue),
  mThresholdCounter(0),
  mpTrajectoryProblem(NULL),
  mCompleteInitialState(),
  mpInitialStateTime(NULL),
  mResiduals(0),
  mRMS(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mSD(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mParameterSD(0),
  mFisher(0, 0),
  mpFisherMatrixInterface(NULL),
  mpFisherMatrix(NULL),
  mFisherEigenvalues(0, 0),
  mpFisherEigenvaluesMatrixInterface(NULL),
  mpFisherEigenvaluesMatrix(NULL),
  mFisherEigenvectors(0, 0),
  mpFisherEigenvectorsMatrixInterface(NULL),
  mpFisherEigenvectorsMatrix(NULL),
  mFisherScaled(0, 0),
  mpFisherScaledMatrixInterface(NULL),
  mpFisherScaledMatrix(NULL),
  mFisherScaledEigenvalues(0, 0),
  mpFisherScaledEigenvaluesMatrixInterface(NULL),
  mpFisherScaledEigenvaluesMatrix(NULL),
  mFisherScaledEigenvectors(0, 0),
  mpFisherScaledEigenvectorsMatrixInterface(NULL),
  mpFisherScaledEigenvectorsMatrix(NULL),
  mCorrelation(0, 0),
  mpCorrelationMatrixInterface(NULL),
  mpCorrelationMatrix(NULL),
  mpCreateParameterSets(NULL),
  mTrajectoryUpdate(false)

{
  initObjects();
  initializeParameter();
}

// copy constructor
CFitProblem::CFitProblem(const CFitProblem& src,
                         const CCopasiContainer * pParent):
  COptProblem(src, pParent),
  mpParmSteadyStateCN(NULL),
  mpParmTimeCourseCN(NULL),
  mpExperimentSet(NULL),
  mpSteadyState(NULL),
  mpTrajectory(NULL),
  mExperimentValues(0, 0),
  mExperimentConstraints(0, 0),
  mExperimentDependentValues(src.mExperimentDependentValues),
  mpCrossValidationSet(NULL),
  mCrossValidationValues(0, 0),
  mCrossValidationConstraints(0, 0),
  mCrossValidationDependentValues(src.mCrossValidationDependentValues),
  mCrossValidationSolutionValue(mWorstValue),
  mCrossValidationRMS(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationSD(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationObjective(mWorstValue),
  mThresholdCounter(0),
  mpTrajectoryProblem(NULL),
  mResiduals(src.mResiduals),
  mRMS(src.mRMS),
  mSD(src.mSD),
  mParameterSD(src.mParameterSD),
  mFisher(src.mFisher),
  mpFisherMatrixInterface(NULL),
  mpFisherMatrix(NULL),
  mFisherEigenvalues(src.mFisherEigenvalues),
  mpFisherEigenvaluesMatrixInterface(NULL),
  mpFisherEigenvaluesMatrix(NULL),
  mFisherEigenvectors(src.mFisherEigenvectors),
  mpFisherEigenvectorsMatrixInterface(NULL),
  mpFisherEigenvectorsMatrix(NULL),
  mFisherScaled(src.mFisherScaled),
  mpFisherScaledMatrixInterface(NULL),
  mpFisherScaledMatrix(NULL),
  mFisherScaledEigenvalues(src.mFisherScaledEigenvalues),
  mpFisherScaledEigenvaluesMatrixInterface(NULL),
  mpFisherScaledEigenvaluesMatrix(NULL),
  mFisherScaledEigenvectors(src.mFisherScaledEigenvectors),
  mpFisherScaledEigenvectorsMatrixInterface(NULL),
  mpFisherScaledEigenvectorsMatrix(NULL),
  mCorrelation(src.mCorrelation),
  mpCorrelationMatrixInterface(NULL),
  mpCorrelationMatrix(NULL),
  mpCreateParameterSets(NULL),
  mTrajectoryUpdate(false)
{
  initObjects();
  initializeParameter();
}

// Destructor
CFitProblem::~CFitProblem()
{
  pdelete(mpTrajectoryProblem);
  pdelete(mpFisherMatrixInterface);
  pdelete(mpFisherMatrix);
  pdelete(mpFisherEigenvaluesMatrixInterface);
  pdelete(mpFisherEigenvaluesMatrix);
  pdelete(mpFisherEigenvectorsMatrixInterface);
  pdelete(mpFisherEigenvectorsMatrix);
  pdelete(mpFisherScaledMatrixInterface);
  pdelete(mpFisherScaledMatrix);
  pdelete(mpFisherScaledEigenvaluesMatrixInterface);
  pdelete(mpFisherScaledEigenvaluesMatrix);
  pdelete(mpFisherScaledEigenvectorsMatrixInterface);
  pdelete(mpFisherScaledEigenvectorsMatrix);
  pdelete(mpCorrelationMatrixInterface);
  pdelete(mpCorrelationMatrix);
}

void CFitProblem::initObjects()
{
  addObjectReference("Validation Solution", mCrossValidationSolutionValue, CCopasiObject::ValueDbl);
  addObjectReference("Validation Objective", mCrossValidationObjective, CCopasiObject::ValueDbl);

  mpFisherMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisher);
  mpFisherMatrix = new CArrayAnnotation("Fisher Information Matrix", this, mpFisherMatrixInterface, false);
  mpFisherMatrix->setDescription("Fisher Information Matrix");
  mpFisherMatrix->setDimensionDescription(0, "Parameters");
  mpFisherMatrix->setDimensionDescription(1, "Parameters");
  mpFisherMatrix->setMode(CArrayAnnotation::STRINGS);

  mpFisherEigenvaluesMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherEigenvalues);
  mpFisherEigenvaluesMatrix = new CArrayAnnotation("FIM Eigenvalues", this, mpFisherEigenvaluesMatrixInterface, false);
  mpFisherEigenvaluesMatrix->setDescription("FIM Eigenvalues");
  mpFisherEigenvaluesMatrix->setDimensionDescription(0, "Eigenvalues");
  mpFisherEigenvaluesMatrix->setDimensionDescription(1, "Result");
  mpFisherEigenvaluesMatrix->setMode(CArrayAnnotation::NUMBERS);

  mpFisherEigenvectorsMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherEigenvectors);
  mpFisherEigenvectorsMatrix = new CArrayAnnotation("FIM Eigenvectors", this, mpFisherEigenvectorsMatrixInterface, false);
  mpFisherEigenvectorsMatrix->setDescription("FIM Eigenvectors");
  mpFisherEigenvectorsMatrix->setDimensionDescription(0, "Eigenvectors");
  mpFisherEigenvectorsMatrix->setDimensionDescription(1, "Parameters");
  mpFisherEigenvectorsMatrix->setMode(0, CArrayAnnotation::NUMBERS);
  mpFisherEigenvectorsMatrix->setMode(1, CArrayAnnotation::STRINGS);

  mpFisherScaledMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherScaled);
  mpFisherScaledMatrix = new CArrayAnnotation("Fisher Information Matrix (scaled)", this, mpFisherScaledMatrixInterface, false);
  mpFisherScaledMatrix->setDescription("Fisher Information Matrix (scaled)");
  mpFisherScaledMatrix->setDimensionDescription(0, "Parameters");
  mpFisherScaledMatrix->setDimensionDescription(1, "Parameters");
  mpFisherScaledMatrix->setMode(CArrayAnnotation::STRINGS);

  mpFisherScaledEigenvaluesMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherScaledEigenvalues);
  mpFisherScaledEigenvaluesMatrix = new CArrayAnnotation("FIM Eigenvalues (scaled)", this, mpFisherScaledEigenvaluesMatrixInterface, false);
  mpFisherScaledEigenvaluesMatrix->setDescription("FIM Eigenvalues (scaled)");
  mpFisherScaledEigenvaluesMatrix->setDimensionDescription(0, "Eigenvalues");
  mpFisherScaledEigenvaluesMatrix->setDimensionDescription(1, "Result");
  mpFisherScaledEigenvaluesMatrix->setMode(CArrayAnnotation::NUMBERS);

  mpFisherScaledEigenvectorsMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherScaledEigenvectors);
  mpFisherScaledEigenvectorsMatrix = new CArrayAnnotation("FIM Eigenvectors (scaled)", this, mpFisherScaledEigenvectorsMatrixInterface, false);
  mpFisherScaledEigenvectorsMatrix->setDescription("FIM Eigenvectors (scaled)");
  mpFisherScaledEigenvectorsMatrix->setDimensionDescription(0, "Eigenvectors");
  mpFisherScaledEigenvectorsMatrix->setDimensionDescription(1, "Parameters");
  mpFisherScaledEigenvectorsMatrix->setMode(0, CArrayAnnotation::NUMBERS);
  mpFisherScaledEigenvectorsMatrix->setMode(1, CArrayAnnotation::STRINGS);

  mpCorrelationMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mCorrelation);
  mpCorrelationMatrix = new CArrayAnnotation("Correlation Matrix", this, mpCorrelationMatrixInterface, false);
  mpCorrelationMatrix->setDescription("Correlation Matrix");
  mpCorrelationMatrix->setDimensionDescription(0, "Parameters");
  mpCorrelationMatrix->setDimensionDescription(1, "Parameters");
  mpCorrelationMatrix->setMode(CArrayAnnotation::STRINGS);
}

void CFitProblem::initializeParameter()
{
  removeParameter("Subtask");
  mpParmSubtaskCN = NULL;
  removeParameter("ObjectiveExpression");
  mpParmObjectiveExpression = NULL;
  *mpParmMaximize = false;

  mpParmSteadyStateCN = assertParameter("Steady-State", CCopasiParameter::CN, CCopasiObjectName(""));
  mpParmTimeCourseCN = assertParameter("Time-Course", CCopasiParameter::CN, CCopasiObjectName(""));
  mpCreateParameterSets = assertParameter("Create Parameter Sets", CCopasiParameter::BOOL, false);

  assertGroup("Experiment Set");

  assertGroup("Validation Set");

  elevateChildren();
}

void CFitProblem::setCreateParameterSets(const bool & create)
{*mpCreateParameterSets = create;}

const bool & CFitProblem::getCreateParameterSets() const
{return *mpCreateParameterSets;}

bool CFitProblem::elevateChildren()
{
  // This call is necessary since CFitProblem is derived from COptProblem.
  if (!COptProblem::elevateChildren()) return false;

  // Due to a naming conflict the following parameters may have been overwritten during
  // the load of a CopasiML file we replace them with default values if that was the case.
  mpParmSteadyStateCN = assertParameter("Steady-State", CCopasiParameter::CN, CCopasiObjectName(""));
  mpParmTimeCourseCN = assertParameter("Time-Course", CCopasiParameter::CN, CCopasiObjectName(""));

  CCopasiVectorN< CCopasiTask > * pTasks = NULL;
  CCopasiDataModel* pDataModel = getObjectDataModel();

  if (pDataModel)
    pTasks = pDataModel->getTaskList();

  if (pTasks == NULL)
    pTasks = dynamic_cast<CCopasiVectorN< CCopasiTask > *>(getObjectAncestor("Vector"));

  if (pTasks)
    {
      size_t i, imax = pTasks->size();

      if (!mpParmSteadyStateCN->compare(0, 5 , "Task_") ||
          *mpParmSteadyStateCN == "")
        for (i = 0; i < imax; i++)
          if (pTasks->operator[](i).getType() == CTaskEnum::steadyState)
            {
              *mpParmSteadyStateCN = pTasks->operator[](i).getCN();
              break;
            }

      if (!mpParmTimeCourseCN->compare(0, 5 , "Task_") ||
          *mpParmTimeCourseCN == "")
        for (i = 0; i < imax; i++)
          if (pTasks->operator[](i).getType() == CTaskEnum::timeCourse)
            {
              *mpParmTimeCourseCN = pTasks->operator[](i).getCN();
              break;
            }
    }

  std::map<std::string, std::string> ExperimentMap;
  CCopasiParameterGroup * pGroup;
  CExperiment * pExperiment;

  std::vector<CCopasiParameter *> * pExperiments =
    &getGroup("Experiment Set")->CCopasiParameter::getValue< CCopasiParameterGroup::elements >();
  std::vector<CCopasiParameter *>::iterator itExp;
  std::vector<CCopasiParameter *>::iterator endExp;

  for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
    if ((pGroup = dynamic_cast< CCopasiParameterGroup * >(*itExp)) != NULL &&
        pGroup->getParameter("Key") != NULL)
      ExperimentMap[pGroup->getValue< std::string >("Key")] = (*itExp)->getObjectName();

  mpExperimentSet =
    elevate<CExperimentSet, CCopasiParameterGroup>(getGroup("Experiment Set"));

  if (!mpExperimentSet) return false;

  std::map<std::string, std::string>::iterator itMap;
  std::map<std::string, std::string>::iterator endMap;

  for (itMap = ExperimentMap.begin(), endMap = ExperimentMap.end(); itMap != endMap; ++itMap)
    {
      pExperiment = mpExperimentSet->getExperiment(itMap->second);
      itMap->second = pExperiment->CCopasiParameter::getKey();
      pExperiment->setValue("Key", itMap->second);
    }

  std::map<std::string, std::string> CrossValidationMap;

  // We have old CopasiML files (only snapshots and test releases), which use
  // "Cross Validation Set"
  pGroup = getGroup("Cross Validation Set");

  if (pGroup != NULL)
    {
      removeParameter("Validation Set");
      pGroup->setObjectName("Validation Set");
    }

  pExperiments =
    &getGroup("Validation Set")->CCopasiParameter::getValue< CCopasiParameterGroup::elements >();

  for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
    if ((pGroup = dynamic_cast< CCopasiParameterGroup * >(*itExp)) != NULL &&
        pGroup->getParameter("Key") != NULL)
      CrossValidationMap[pGroup->getValue< std::string >("Key")] = (*itExp)->getObjectName();

  // This intermediate elevation step should be not needed but Viusal C fails when directly
  // going to the CCrossValidationSet.
  elevate< CExperimentSet, CCopasiParameterGroup >(getGroup("Validation Set"));
  mpCrossValidationSet =
    elevate< CCrossValidationSet, CCopasiParameterGroup >(getGroup("Validation Set"));

  if (!mpCrossValidationSet) return false;

  for (itMap = CrossValidationMap.begin(), endMap = CrossValidationMap.end(); itMap != endMap; ++itMap)
    {
      pExperiment = mpCrossValidationSet->getExperiment(itMap->second);
      itMap->second = pExperiment->CCopasiParameter::getKey();
      pExperiment->setValue("Key", itMap->second);
    }

  std::vector<COptItem * >::iterator it = mpOptItems->begin();
  std::vector<COptItem * >::iterator end = mpOptItems->end();

  for (; it != end; ++it)
    {
      if (!((*it) = elevate<CFitItem, COptItem>(*it)))
        return false;

      pExperiments =
        &(*it)->getParameter("Affected Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(ExperimentMap[(*itExp)->getValue< std::string >()]);

      pExperiments =
        &(*it)->getParameter("Affected Cross Validation Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(CrossValidationMap[(*itExp)->getValue< std::string >()]);
    }

  it = mpConstraintItems->begin();
  end = mpConstraintItems->end();

  for (; it != end; ++it)
    {
      if (!((*it) = elevate<CFitConstraint, COptItem>(*it)))
        return false;

      pExperiments =
        &(*it)->getParameter("Affected Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(ExperimentMap[(*itExp)->getValue< std::string >()]);

      pExperiments =
        &(*it)->getParameter("Affected Cross Validation Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(CrossValidationMap[(*itExp)->getValue< std::string >()]);
    }

  return true;
}

bool CFitProblem::setCallBack(CProcessReport * pCallBack)
{return COptProblem::setCallBack(pCallBack);}

bool CFitProblem::initialize()
{
  bool success = true;

  mHaveStatistics = false;
  mStoreResults = false;

  if (!COptProblem::initialize())
    {
      while (CCopasiMessage::peekLastMessage().getNumber() == MCOptimization + 5 ||
             CCopasiMessage::peekLastMessage().getNumber() == MCOptimization + 7)
        CCopasiMessage::getLastMessage();

      if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::WARNING &&
          CCopasiMessage::peekLastMessage().getNumber() != MCCopasiMessage + 1)

        success = false;
    }

  CCopasiDataModel * pDataModel = getObjectDataModel();
  assert(pDataModel != NULL);

  // We only need to initialize the steady-state task if steady-state data is present.
  if (mpExperimentSet->hasDataForTaskType(CTaskEnum::steadyState))
    {
      mpSteadyState =
        dynamic_cast< CSteadyStateTask * >(const_cast< CCopasiObject * >(CObjectInterface::DataObject(getObjectFromCN(*mpParmSteadyStateCN))));

      if (mpSteadyState == NULL)
        {
          mpSteadyState =
            static_cast<CSteadyStateTask *>(&pDataModel->getTaskList()->operator[]("Steady-State"));
        }

      if (mpSteadyState == NULL) fatalError();

      *mpParmSteadyStateCN = mpSteadyState->getCN();
      mpSteadyState->initialize(CCopasiTask::NO_OUTPUT, NULL, NULL);
    }
  else
    {
      mpSteadyState = NULL;
    }

  pdelete(mpTrajectoryProblem);

  // We only need to initialize the trajectory task if time course data is present.
  if (mpExperimentSet->hasDataForTaskType(CTaskEnum::timeCourse))
    {
      mpTrajectory =
        dynamic_cast< CTrajectoryTask * >(const_cast< CCopasiObject * >(CObjectInterface::DataObject(getObjectFromCN(*mpParmTimeCourseCN))));

      if (mpTrajectory == NULL)
        {
          mpTrajectory =
            static_cast<CTrajectoryTask *>(&pDataModel->getTaskList()->operator[]("Time-Course"));
        }

      if (mpTrajectory == NULL) fatalError();

      *mpParmTimeCourseCN = mpTrajectory->getCN();

      // do not update initial values when running fit
      mTrajectoryUpdate = mpTrajectory->isUpdateModel();
      mpTrajectory->setUpdateModel(false);

      mpTrajectory->initialize(CCopasiTask::NO_OUTPUT, NULL, NULL);

      mpTrajectoryProblem =
        new CTrajectoryProblem(*static_cast<CTrajectoryProblem *>(mpTrajectory->getProblem()), NO_PARENT);
    }
  else
    {
      mpTrajectory = NULL;
    }

  mCompleteInitialState = mpContainer->getCompleteInitialState();
  mpInitialStateTime = mpContainer->getInitialState().array() + mpContainer->getCountFixedEventTargets();

  success &= mpExperimentSet->compile(mpContainer);

  // Initialize the object set which the experiment independent objects.
  std::vector< CObjectInterface::ObjectSet > ObjectSet;
  ObjectSet.resize(mpExperimentSet->getExperimentCount());
  size_t i, imax = mpExperimentSet->getExperimentCount();

  // Build a matrix of experiment and experiment local items.
  mExperimentValues.resize(mpExperimentSet->getExperimentCount(), mpOptItems->size());
  mExperimentValues = NULL;

  mExperimentInitialUpdates.resize(mpExperimentSet->getExperimentCount());

  std::vector<COptItem * >::iterator it = mpOptItems->begin();
  std::vector<COptItem * >::iterator end = mpOptItems->end();

  std::vector<COptItem * >::iterator itTmp;

  CFitItem * pItem;
  size_t j;
  size_t Index;

  imax = mSolutionVariables.size();

  mFisher.resize(imax, imax);
  mpFisherMatrix->resize();
  mFisherEigenvalues.resize(imax, 1);
  mpFisherEigenvaluesMatrix->resize();
  mFisherEigenvectors.resize(imax, imax);
  mpFisherEigenvectorsMatrix->resize();
  mFisherScaled.resize(imax, imax);
  mpFisherScaledMatrix->resize();
  mFisherScaledEigenvalues.resize(imax, 1);
  mpFisherScaledEigenvaluesMatrix->resize();
  mFisherScaledEigenvectors.resize(imax, imax);
  mpFisherScaledEigenvectorsMatrix->resize();
  mCorrelation.resize(imax, imax);
  mpCorrelationMatrix->resize();

  for (j = 0; it != end; ++it, j++)
    {
      pItem = static_cast<CFitItem *>(*it);
      pItem->updateBounds(mpOptItems->begin());

      // We cannot directly change the container values as multiple parameters
      // may point to the same value.
      mContainerVariables[j] = const_cast< C_FLOAT64 * >(&pItem->getLocalValue());

      std::string Annotation = pItem->getObjectDisplayName();

      imax = pItem->getExperimentCount();

      if (imax == 0)
        {
          for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
            {
              const CObjectInterface * object = pItem->getObject();

              if (object != NULL)
                {
                  mExperimentValues(i, j) = (C_FLOAT64 *)object->getValuePointer();
                  ObjectSet[i].insert(object);
                }
            }
        }
      else
        {
          Annotation += "; {" + pItem->getExperiments() + "}";

          for (i = 0; i < imax; i++)
            {
              if ((Index = mpExperimentSet->keyToIndex(pItem->getExperiment(i))) == C_INVALID_INDEX)
                return false;

              mExperimentValues(Index, j) = (C_FLOAT64 *) pItem->getObject()->getValuePointer();
              ObjectSet[Index].insert(pItem->getObject());
            };
        }

      mpFisherMatrix->setAnnotationString(0, j, Annotation);
      mpFisherMatrix->setAnnotationString(1, j, Annotation);
      mpFisherEigenvectorsMatrix->setAnnotationString(1, j, Annotation);
      mpFisherScaledMatrix->setAnnotationString(0, j, Annotation);
      mpFisherScaledMatrix->setAnnotationString(1, j, Annotation);
      mpFisherScaledEigenvectorsMatrix->setAnnotationString(1, j, Annotation);
      mpCorrelationMatrix->setAnnotationString(0, j, Annotation);
      mpCorrelationMatrix->setAnnotationString(1, j, Annotation);
    }

  // Create a joined sequence of update methods for parameters and independent values.
  for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
    {
      mpContainer->getInitialDependencies().getUpdateSequence(mExperimentInitialUpdates[i], CMath::UpdateMoieties, ObjectSet[i], mpContainer->getInitialStateObjects());
    }

  // Build a matrix of experiment and constraint items;
  mExperimentConstraints.resize(mpExperimentSet->getExperimentCount(),
                                mpConstraintItems->size());
  mExperimentConstraints = NULL;
  mExperimentConstraintUpdates.resize(mpExperimentSet->getExperimentCount());
  ObjectSet.clear();
  ObjectSet.resize(mpExperimentSet->getExperimentCount());

  it = mpConstraintItems->begin();
  end = mpConstraintItems->end();

  CFitConstraint * pConstraint;
  std::set< const CCopasiObject * >::const_iterator itDepend;
  std::set< const CCopasiObject * >::const_iterator endDepend;

  for (j = 0; it != end; ++it, j++)
    {
      pConstraint = static_cast<CFitConstraint *>(*it);
      itDepend = pConstraint->getDirectDependencies().begin();
      endDepend = pConstraint->getDirectDependencies().end();
      imax = pConstraint->getExperimentCount();

      if (imax == 0)
        {
          for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
            {
              mExperimentConstraints(i, j) = pConstraint;
              ObjectSet[i].insert(itDepend, endDepend);
            }
        }
      else
        {
          for (i = 0; i < imax; i++)
            {
              if ((Index = mpExperimentSet->keyToIndex(pConstraint->getExperiment(i))) == C_INVALID_INDEX)
                return false;

              mExperimentConstraints(Index, j) = pConstraint;
              ObjectSet[Index].insert(itDepend, endDepend);
            };
        }
    }

  for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
    {
      mpContainer->getTransientDependencies().getUpdateSequence(mExperimentConstraintUpdates[i], CMath::Default,
          mpContainer->getStateObjects(false), ObjectSet[i],
          mpContainer->getSimulationUpToDateObjects());
    }

  mExperimentDependentValues.resize(mpExperimentSet->getDataPointCount());

  if (!mpCrossValidationSet->compile(mpContainer)) return false;

  // Initialize the object set which the experiment independent objects.
  ObjectSet.clear();
  ObjectSet.resize(mpCrossValidationSet->getExperimentCount());

  for (i = 0, imax = mpCrossValidationSet->getExperimentCount(); i < imax; i++)
    {
      ObjectSet[i] = mpCrossValidationSet->getExperiment(i)->getIndependentObjects();<commit_msg>Fixed Bug 2381. The update sequence for functional constraints was incorrectly generated.<commit_after>// Copyright (C) 2017 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and University of
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2010 - 2016 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by <NAME>, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <cmath>

#include "copasi.h"

#include "CFitProblem.h"
#include "CFitItem.h"
#include "CFitTask.h"
#include "CExperimentSet.h"
#include "CExperiment.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "math/CMathContainer.h"
#include "model/CModel.h"
#include "report/CCopasiObjectReference.h"
#include "report/CKeyFactory.h"
#include "steadystate/CSteadyStateTask.h"
#include "trajectory/CTrajectoryTask.h"
#include "trajectory/CTrajectoryProblem.h"
#include "utilities/CProcessReport.h"
#include "utilities/CCopasiException.h"
#include "utilities/CAnnotatedMatrix.h"

#include "lapack/blaswrap.h"           //use blas
#include "lapack/lapackwrap.h"        //use CLAPACK

//  Default constructor
CFitProblem::CFitProblem(const CTaskEnum::Task & type,
                         const CCopasiContainer * pParent):
  COptProblem(type, pParent),
  mpParmSteadyStateCN(NULL),
  mpParmTimeCourseCN(NULL),
  mpExperimentSet(NULL),
  mpSteadyState(NULL),
  mpTrajectory(NULL),
  mExperimentValues(0, 0),
  mExperimentConstraints(0, 0),
  mExperimentDependentValues(0),
  mpCrossValidationSet(NULL),
  mCrossValidationValues(0, 0),
  mCrossValidationConstraints(0, 0),
  mCrossValidationDependentValues(0),
  mCrossValidationSolutionValue(mWorstValue),
  mCrossValidationRMS(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationSD(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationObjective(mWorstValue),
  mThresholdCounter(0),
  mpTrajectoryProblem(NULL),
  mCompleteInitialState(),
  mpInitialStateTime(NULL),
  mResiduals(0),
  mRMS(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mSD(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mParameterSD(0),
  mFisher(0, 0),
  mpFisherMatrixInterface(NULL),
  mpFisherMatrix(NULL),
  mFisherEigenvalues(0, 0),
  mpFisherEigenvaluesMatrixInterface(NULL),
  mpFisherEigenvaluesMatrix(NULL),
  mFisherEigenvectors(0, 0),
  mpFisherEigenvectorsMatrixInterface(NULL),
  mpFisherEigenvectorsMatrix(NULL),
  mFisherScaled(0, 0),
  mpFisherScaledMatrixInterface(NULL),
  mpFisherScaledMatrix(NULL),
  mFisherScaledEigenvalues(0, 0),
  mpFisherScaledEigenvaluesMatrixInterface(NULL),
  mpFisherScaledEigenvaluesMatrix(NULL),
  mFisherScaledEigenvectors(0, 0),
  mpFisherScaledEigenvectorsMatrixInterface(NULL),
  mpFisherScaledEigenvectorsMatrix(NULL),
  mCorrelation(0, 0),
  mpCorrelationMatrixInterface(NULL),
  mpCorrelationMatrix(NULL),
  mpCreateParameterSets(NULL),
  mTrajectoryUpdate(false)

{
  initObjects();
  initializeParameter();
}

// copy constructor
CFitProblem::CFitProblem(const CFitProblem& src,
                         const CCopasiContainer * pParent):
  COptProblem(src, pParent),
  mpParmSteadyStateCN(NULL),
  mpParmTimeCourseCN(NULL),
  mpExperimentSet(NULL),
  mpSteadyState(NULL),
  mpTrajectory(NULL),
  mExperimentValues(0, 0),
  mExperimentConstraints(0, 0),
  mExperimentDependentValues(src.mExperimentDependentValues),
  mpCrossValidationSet(NULL),
  mCrossValidationValues(0, 0),
  mCrossValidationConstraints(0, 0),
  mCrossValidationDependentValues(src.mCrossValidationDependentValues),
  mCrossValidationSolutionValue(mWorstValue),
  mCrossValidationRMS(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationSD(std::numeric_limits<C_FLOAT64>::quiet_NaN()),
  mCrossValidationObjective(mWorstValue),
  mThresholdCounter(0),
  mpTrajectoryProblem(NULL),
  mResiduals(src.mResiduals),
  mRMS(src.mRMS),
  mSD(src.mSD),
  mParameterSD(src.mParameterSD),
  mFisher(src.mFisher),
  mpFisherMatrixInterface(NULL),
  mpFisherMatrix(NULL),
  mFisherEigenvalues(src.mFisherEigenvalues),
  mpFisherEigenvaluesMatrixInterface(NULL),
  mpFisherEigenvaluesMatrix(NULL),
  mFisherEigenvectors(src.mFisherEigenvectors),
  mpFisherEigenvectorsMatrixInterface(NULL),
  mpFisherEigenvectorsMatrix(NULL),
  mFisherScaled(src.mFisherScaled),
  mpFisherScaledMatrixInterface(NULL),
  mpFisherScaledMatrix(NULL),
  mFisherScaledEigenvalues(src.mFisherScaledEigenvalues),
  mpFisherScaledEigenvaluesMatrixInterface(NULL),
  mpFisherScaledEigenvaluesMatrix(NULL),
  mFisherScaledEigenvectors(src.mFisherScaledEigenvectors),
  mpFisherScaledEigenvectorsMatrixInterface(NULL),
  mpFisherScaledEigenvectorsMatrix(NULL),
  mCorrelation(src.mCorrelation),
  mpCorrelationMatrixInterface(NULL),
  mpCorrelationMatrix(NULL),
  mpCreateParameterSets(NULL),
  mTrajectoryUpdate(false)
{
  initObjects();
  initializeParameter();
}

// Destructor
CFitProblem::~CFitProblem()
{
  pdelete(mpTrajectoryProblem);
  pdelete(mpFisherMatrixInterface);
  pdelete(mpFisherMatrix);
  pdelete(mpFisherEigenvaluesMatrixInterface);
  pdelete(mpFisherEigenvaluesMatrix);
  pdelete(mpFisherEigenvectorsMatrixInterface);
  pdelete(mpFisherEigenvectorsMatrix);
  pdelete(mpFisherScaledMatrixInterface);
  pdelete(mpFisherScaledMatrix);
  pdelete(mpFisherScaledEigenvaluesMatrixInterface);
  pdelete(mpFisherScaledEigenvaluesMatrix);
  pdelete(mpFisherScaledEigenvectorsMatrixInterface);
  pdelete(mpFisherScaledEigenvectorsMatrix);
  pdelete(mpCorrelationMatrixInterface);
  pdelete(mpCorrelationMatrix);
}

void CFitProblem::initObjects()
{
  addObjectReference("Validation Solution", mCrossValidationSolutionValue, CCopasiObject::ValueDbl);
  addObjectReference("Validation Objective", mCrossValidationObjective, CCopasiObject::ValueDbl);

  mpFisherMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisher);
  mpFisherMatrix = new CArrayAnnotation("Fisher Information Matrix", this, mpFisherMatrixInterface, false);
  mpFisherMatrix->setDescription("Fisher Information Matrix");
  mpFisherMatrix->setDimensionDescription(0, "Parameters");
  mpFisherMatrix->setDimensionDescription(1, "Parameters");
  mpFisherMatrix->setMode(CArrayAnnotation::STRINGS);

  mpFisherEigenvaluesMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherEigenvalues);
  mpFisherEigenvaluesMatrix = new CArrayAnnotation("FIM Eigenvalues", this, mpFisherEigenvaluesMatrixInterface, false);
  mpFisherEigenvaluesMatrix->setDescription("FIM Eigenvalues");
  mpFisherEigenvaluesMatrix->setDimensionDescription(0, "Eigenvalues");
  mpFisherEigenvaluesMatrix->setDimensionDescription(1, "Result");
  mpFisherEigenvaluesMatrix->setMode(CArrayAnnotation::NUMBERS);

  mpFisherEigenvectorsMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherEigenvectors);
  mpFisherEigenvectorsMatrix = new CArrayAnnotation("FIM Eigenvectors", this, mpFisherEigenvectorsMatrixInterface, false);
  mpFisherEigenvectorsMatrix->setDescription("FIM Eigenvectors");
  mpFisherEigenvectorsMatrix->setDimensionDescription(0, "Eigenvectors");
  mpFisherEigenvectorsMatrix->setDimensionDescription(1, "Parameters");
  mpFisherEigenvectorsMatrix->setMode(0, CArrayAnnotation::NUMBERS);
  mpFisherEigenvectorsMatrix->setMode(1, CArrayAnnotation::STRINGS);

  mpFisherScaledMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherScaled);
  mpFisherScaledMatrix = new CArrayAnnotation("Fisher Information Matrix (scaled)", this, mpFisherScaledMatrixInterface, false);
  mpFisherScaledMatrix->setDescription("Fisher Information Matrix (scaled)");
  mpFisherScaledMatrix->setDimensionDescription(0, "Parameters");
  mpFisherScaledMatrix->setDimensionDescription(1, "Parameters");
  mpFisherScaledMatrix->setMode(CArrayAnnotation::STRINGS);

  mpFisherScaledEigenvaluesMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherScaledEigenvalues);
  mpFisherScaledEigenvaluesMatrix = new CArrayAnnotation("FIM Eigenvalues (scaled)", this, mpFisherScaledEigenvaluesMatrixInterface, false);
  mpFisherScaledEigenvaluesMatrix->setDescription("FIM Eigenvalues (scaled)");
  mpFisherScaledEigenvaluesMatrix->setDimensionDescription(0, "Eigenvalues");
  mpFisherScaledEigenvaluesMatrix->setDimensionDescription(1, "Result");
  mpFisherScaledEigenvaluesMatrix->setMode(CArrayAnnotation::NUMBERS);

  mpFisherScaledEigenvectorsMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mFisherScaledEigenvectors);
  mpFisherScaledEigenvectorsMatrix = new CArrayAnnotation("FIM Eigenvectors (scaled)", this, mpFisherScaledEigenvectorsMatrixInterface, false);
  mpFisherScaledEigenvectorsMatrix->setDescription("FIM Eigenvectors (scaled)");
  mpFisherScaledEigenvectorsMatrix->setDimensionDescription(0, "Eigenvectors");
  mpFisherScaledEigenvectorsMatrix->setDimensionDescription(1, "Parameters");
  mpFisherScaledEigenvectorsMatrix->setMode(0, CArrayAnnotation::NUMBERS);
  mpFisherScaledEigenvectorsMatrix->setMode(1, CArrayAnnotation::STRINGS);

  mpCorrelationMatrixInterface = new CCopasiMatrixInterface< CMatrix< C_FLOAT64 > >(&mCorrelation);
  mpCorrelationMatrix = new CArrayAnnotation("Correlation Matrix", this, mpCorrelationMatrixInterface, false);
  mpCorrelationMatrix->setDescription("Correlation Matrix");
  mpCorrelationMatrix->setDimensionDescription(0, "Parameters");
  mpCorrelationMatrix->setDimensionDescription(1, "Parameters");
  mpCorrelationMatrix->setMode(CArrayAnnotation::STRINGS);
}

void CFitProblem::initializeParameter()
{
  removeParameter("Subtask");
  mpParmSubtaskCN = NULL;
  removeParameter("ObjectiveExpression");
  mpParmObjectiveExpression = NULL;
  *mpParmMaximize = false;

  mpParmSteadyStateCN = assertParameter("Steady-State", CCopasiParameter::CN, CCopasiObjectName(""));
  mpParmTimeCourseCN = assertParameter("Time-Course", CCopasiParameter::CN, CCopasiObjectName(""));
  mpCreateParameterSets = assertParameter("Create Parameter Sets", CCopasiParameter::BOOL, false);

  assertGroup("Experiment Set");

  assertGroup("Validation Set");

  elevateChildren();
}

void CFitProblem::setCreateParameterSets(const bool & create)
{*mpCreateParameterSets = create;}

const bool & CFitProblem::getCreateParameterSets() const
{return *mpCreateParameterSets;}

bool CFitProblem::elevateChildren()
{
  // This call is necessary since CFitProblem is derived from COptProblem.
  if (!COptProblem::elevateChildren()) return false;

  // Due to a naming conflict the following parameters may have been overwritten during
  // the load of a CopasiML file we replace them with default values if that was the case.
  mpParmSteadyStateCN = assertParameter("Steady-State", CCopasiParameter::CN, CCopasiObjectName(""));
  mpParmTimeCourseCN = assertParameter("Time-Course", CCopasiParameter::CN, CCopasiObjectName(""));

  CCopasiVectorN< CCopasiTask > * pTasks = NULL;
  CCopasiDataModel* pDataModel = getObjectDataModel();

  if (pDataModel)
    pTasks = pDataModel->getTaskList();

  if (pTasks == NULL)
    pTasks = dynamic_cast<CCopasiVectorN< CCopasiTask > *>(getObjectAncestor("Vector"));

  if (pTasks)
    {
      size_t i, imax = pTasks->size();

      if (!mpParmSteadyStateCN->compare(0, 5 , "Task_") ||
          *mpParmSteadyStateCN == "")
        for (i = 0; i < imax; i++)
          if (pTasks->operator[](i).getType() == CTaskEnum::steadyState)
            {
              *mpParmSteadyStateCN = pTasks->operator[](i).getCN();
              break;
            }

      if (!mpParmTimeCourseCN->compare(0, 5 , "Task_") ||
          *mpParmTimeCourseCN == "")
        for (i = 0; i < imax; i++)
          if (pTasks->operator[](i).getType() == CTaskEnum::timeCourse)
            {
              *mpParmTimeCourseCN = pTasks->operator[](i).getCN();
              break;
            }
    }

  std::map<std::string, std::string> ExperimentMap;
  CCopasiParameterGroup * pGroup;
  CExperiment * pExperiment;

  std::vector<CCopasiParameter *> * pExperiments =
    &getGroup("Experiment Set")->CCopasiParameter::getValue< CCopasiParameterGroup::elements >();
  std::vector<CCopasiParameter *>::iterator itExp;
  std::vector<CCopasiParameter *>::iterator endExp;

  for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
    if ((pGroup = dynamic_cast< CCopasiParameterGroup * >(*itExp)) != NULL &&
        pGroup->getParameter("Key") != NULL)
      ExperimentMap[pGroup->getValue< std::string >("Key")] = (*itExp)->getObjectName();

  mpExperimentSet =
    elevate<CExperimentSet, CCopasiParameterGroup>(getGroup("Experiment Set"));

  if (!mpExperimentSet) return false;

  std::map<std::string, std::string>::iterator itMap;
  std::map<std::string, std::string>::iterator endMap;

  for (itMap = ExperimentMap.begin(), endMap = ExperimentMap.end(); itMap != endMap; ++itMap)
    {
      pExperiment = mpExperimentSet->getExperiment(itMap->second);
      itMap->second = pExperiment->CCopasiParameter::getKey();
      pExperiment->setValue("Key", itMap->second);
    }

  std::map<std::string, std::string> CrossValidationMap;

  // We have old CopasiML files (only snapshots and test releases), which use
  // "Cross Validation Set"
  pGroup = getGroup("Cross Validation Set");

  if (pGroup != NULL)
    {
      removeParameter("Validation Set");
      pGroup->setObjectName("Validation Set");
    }

  pExperiments =
    &getGroup("Validation Set")->CCopasiParameter::getValue< CCopasiParameterGroup::elements >();

  for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
    if ((pGroup = dynamic_cast< CCopasiParameterGroup * >(*itExp)) != NULL &&
        pGroup->getParameter("Key") != NULL)
      CrossValidationMap[pGroup->getValue< std::string >("Key")] = (*itExp)->getObjectName();

  // This intermediate elevation step should be not needed but Viusal C fails when directly
  // going to the CCrossValidationSet.
  elevate< CExperimentSet, CCopasiParameterGroup >(getGroup("Validation Set"));
  mpCrossValidationSet =
    elevate< CCrossValidationSet, CCopasiParameterGroup >(getGroup("Validation Set"));

  if (!mpCrossValidationSet) return false;

  for (itMap = CrossValidationMap.begin(), endMap = CrossValidationMap.end(); itMap != endMap; ++itMap)
    {
      pExperiment = mpCrossValidationSet->getExperiment(itMap->second);
      itMap->second = pExperiment->CCopasiParameter::getKey();
      pExperiment->setValue("Key", itMap->second);
    }

  std::vector<COptItem * >::iterator it = mpOptItems->begin();
  std::vector<COptItem * >::iterator end = mpOptItems->end();

  for (; it != end; ++it)
    {
      if (!((*it) = elevate<CFitItem, COptItem>(*it)))
        return false;

      pExperiments =
        &(*it)->getParameter("Affected Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(ExperimentMap[(*itExp)->getValue< std::string >()]);

      pExperiments =
        &(*it)->getParameter("Affected Cross Validation Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(CrossValidationMap[(*itExp)->getValue< std::string >()]);
    }

  it = mpConstraintItems->begin();
  end = mpConstraintItems->end();

  for (; it != end; ++it)
    {
      if (!((*it) = elevate<CFitConstraint, COptItem>(*it)))
        return false;

      pExperiments =
        &(*it)->getParameter("Affected Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(ExperimentMap[(*itExp)->getValue< std::string >()]);

      pExperiments =
        &(*it)->getParameter("Affected Cross Validation Experiments")->getValue< CCopasiParameterGroup::elements >();

      for (itExp = pExperiments->begin(), endExp = pExperiments->end(); itExp != endExp; ++itExp)
        (*itExp)->setValue(CrossValidationMap[(*itExp)->getValue< std::string >()]);
    }

  return true;
}

bool CFitProblem::setCallBack(CProcessReport * pCallBack)
{return COptProblem::setCallBack(pCallBack);}

bool CFitProblem::initialize()
{
  bool success = true;

  mHaveStatistics = false;
  mStoreResults = false;

  if (!COptProblem::initialize())
    {
      while (CCopasiMessage::peekLastMessage().getNumber() == MCOptimization + 5 ||
             CCopasiMessage::peekLastMessage().getNumber() == MCOptimization + 7)
        CCopasiMessage::getLastMessage();

      if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::WARNING &&
          CCopasiMessage::peekLastMessage().getNumber() != MCCopasiMessage + 1)

        success = false;
    }

  CCopasiDataModel * pDataModel = getObjectDataModel();
  assert(pDataModel != NULL);

  // We only need to initialize the steady-state task if steady-state data is present.
  if (mpExperimentSet->hasDataForTaskType(CTaskEnum::steadyState))
    {
      mpSteadyState =
        dynamic_cast< CSteadyStateTask * >(const_cast< CCopasiObject * >(CObjectInterface::DataObject(getObjectFromCN(*mpParmSteadyStateCN))));

      if (mpSteadyState == NULL)
        {
          mpSteadyState =
            static_cast<CSteadyStateTask *>(&pDataModel->getTaskList()->operator[]("Steady-State"));
        }

      if (mpSteadyState == NULL) fatalError();

      *mpParmSteadyStateCN = mpSteadyState->getCN();
      mpSteadyState->initialize(CCopasiTask::NO_OUTPUT, NULL, NULL);
    }
  else
    {
      mpSteadyState = NULL;
    }

  pdelete(mpTrajectoryProblem);

  // We only need to initialize the trajectory task if time course data is present.
  if (mpExperimentSet->hasDataForTaskType(CTaskEnum::timeCourse))
    {
      mpTrajectory =
        dynamic_cast< CTrajectoryTask * >(const_cast< CCopasiObject * >(CObjectInterface::DataObject(getObjectFromCN(*mpParmTimeCourseCN))));

      if (mpTrajectory == NULL)
        {
          mpTrajectory =
            static_cast<CTrajectoryTask *>(&pDataModel->getTaskList()->operator[]("Time-Course"));
        }

      if (mpTrajectory == NULL) fatalError();

      *mpParmTimeCourseCN = mpTrajectory->getCN();

      // do not update initial values when running fit
      mTrajectoryUpdate = mpTrajectory->isUpdateModel();
      mpTrajectory->setUpdateModel(false);

      mpTrajectory->initialize(CCopasiTask::NO_OUTPUT, NULL, NULL);

      mpTrajectoryProblem =
        new CTrajectoryProblem(*static_cast<CTrajectoryProblem *>(mpTrajectory->getProblem()), NO_PARENT);
    }
  else
    {
      mpTrajectory = NULL;
    }

  mCompleteInitialState = mpContainer->getCompleteInitialState();
  mpInitialStateTime = mpContainer->getInitialState().array() + mpContainer->getCountFixedEventTargets();

  success &= mpExperimentSet->compile(mpContainer);

  // Initialize the object set which the experiment independent objects.
  std::vector< CObjectInterface::ObjectSet > ObjectSet;
  ObjectSet.resize(mpExperimentSet->getExperimentCount());
  size_t i, imax = mpExperimentSet->getExperimentCount();

  // Build a matrix of experiment and experiment local items.
  mExperimentValues.resize(mpExperimentSet->getExperimentCount(), mpOptItems->size());
  mExperimentValues = NULL;

  mExperimentInitialUpdates.resize(mpExperimentSet->getExperimentCount());

  std::vector<COptItem * >::iterator it = mpOptItems->begin();
  std::vector<COptItem * >::iterator end = mpOptItems->end();

  std::vector<COptItem * >::iterator itTmp;

  CFitItem * pItem;
  size_t j;
  size_t Index;

  imax = mSolutionVariables.size();

  mFisher.resize(imax, imax);
  mpFisherMatrix->resize();
  mFisherEigenvalues.resize(imax, 1);
  mpFisherEigenvaluesMatrix->resize();
  mFisherEigenvectors.resize(imax, imax);
  mpFisherEigenvectorsMatrix->resize();
  mFisherScaled.resize(imax, imax);
  mpFisherScaledMatrix->resize();
  mFisherScaledEigenvalues.resize(imax, 1);
  mpFisherScaledEigenvaluesMatrix->resize();
  mFisherScaledEigenvectors.resize(imax, imax);
  mpFisherScaledEigenvectorsMatrix->resize();
  mCorrelation.resize(imax, imax);
  mpCorrelationMatrix->resize();

  for (j = 0; it != end; ++it, j++)
    {
      pItem = static_cast<CFitItem *>(*it);
      pItem->updateBounds(mpOptItems->begin());

      // We cannot directly change the container values as multiple parameters
      // may point to the same value.
      mContainerVariables[j] = const_cast< C_FLOAT64 * >(&pItem->getLocalValue());

      std::string Annotation = pItem->getObjectDisplayName();

      imax = pItem->getExperimentCount();

      if (imax == 0)
        {
          for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
            {
              const CObjectInterface * object = pItem->getObject();

              if (object != NULL)
                {
                  mExperimentValues(i, j) = (C_FLOAT64 *)object->getValuePointer();
                  ObjectSet[i].insert(object);
                }
            }
        }
      else
        {
          Annotation += "; {" + pItem->getExperiments() + "}";

          for (i = 0; i < imax; i++)
            {
              if ((Index = mpExperimentSet->keyToIndex(pItem->getExperiment(i))) == C_INVALID_INDEX)
                return false;

              mExperimentValues(Index, j) = (C_FLOAT64 *) pItem->getObject()->getValuePointer();
              ObjectSet[Index].insert(pItem->getObject());
            };
        }

      mpFisherMatrix->setAnnotationString(0, j, Annotation);
      mpFisherMatrix->setAnnotationString(1, j, Annotation);
      mpFisherEigenvectorsMatrix->setAnnotationString(1, j, Annotation);
      mpFisherScaledMatrix->setAnnotationString(0, j, Annotation);
      mpFisherScaledMatrix->setAnnotationString(1, j, Annotation);
      mpFisherScaledEigenvectorsMatrix->setAnnotationString(1, j, Annotation);
      mpCorrelationMatrix->setAnnotationString(0, j, Annotation);
      mpCorrelationMatrix->setAnnotationString(1, j, Annotation);
    }

  // Create a joined sequence of update methods for parameters and independent values.
  for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
    {
      mpContainer->getInitialDependencies().getUpdateSequence(mExperimentInitialUpdates[i], CMath::UpdateMoieties, ObjectSet[i], mpContainer->getInitialStateObjects());
    }

  // Build a matrix of experiment and constraint items;
  mExperimentConstraints.resize(mpExperimentSet->getExperimentCount(),
                                mpConstraintItems->size());
  mExperimentConstraints = NULL;
  mExperimentConstraintUpdates.resize(mpExperimentSet->getExperimentCount());
  ObjectSet.clear();
  ObjectSet.resize(mpExperimentSet->getExperimentCount());

  it = mpConstraintItems->begin();
  end = mpConstraintItems->end();

  CFitConstraint * pConstraint;

  for (j = 0; it != end; ++it, j++)
    {
      pConstraint = static_cast<CFitConstraint *>(*it);
      imax = pConstraint->getExperimentCount();

      if (imax == 0)
        {
          for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
            {
              mExperimentConstraints(i, j) = pConstraint;
              ObjectSet[i].insert(pConstraint->getObject());
            }
        }
      else
        {
          for (i = 0; i < imax; i++)
            {
              if ((Index = mpExperimentSet->keyToIndex(pConstraint->getExperiment(i))) == C_INVALID_INDEX)
                return false;

              mExperimentConstraints(Index, j) = pConstraint;
              ObjectSet[Index].insert(pConstraint->getObject());
            };
        }
    }

  for (i = 0, imax = mpExperimentSet->getExperimentCount(); i < imax; i++)
    {
      mpContainer->getTransientDependencies().getUpdateSequence(mExperimentConstraintUpdates[i], CMath::Default,
          mpContainer->getStateObjects(false), ObjectSet[i],
          mpContainer->getSimulationUpToDateObjects());
    }

  mExperimentDependentValues.resize(mpExperimentSet->getDataPointCount());

  if (!mpCrossValidationSet->compile(mpContainer)) return false;

  // Initialize the object set which the experiment independent objects.
  ObjectSet.clear();
  ObjectSet.resize(mpCrossValidationSet->getExperimentCount());

  for (i = 0, imax = mpCrossValidationSet->getExperimentCount(); i < imax; i++)
    {
      ObjectSet[i] = mpCrossValidationSet->getExperiment(i)->getIndependentObjects();
{'fraction_non_alphanumeric': 0.12488419865469046, 'fraction_numerical': 0.005800136947677931, 'mean_word_length': 4.916944709246902, 'pattern_counts': {'":': 0, '<': 162, '<?xml version=': 0, '>': 484, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5537338', 'n_tokens_mistral': 15720, 'n_tokens_neox': 14855, 'n_words': 2614}