ErrorCode CGcdData::TranslateToGCD()

in cli/gcdmodel.cpp [142:312]


ErrorCode CGcdData::TranslateToGCD()
{
    Model* rootModel = new Model( L"", GenerationType::MixedOrder, _modelData.Order, _modelData.RandSeed );
    Models.push_back( rootModel );

    _task.SetRootModel( rootModel );
    _task.SetGenerationMode( _modelData.GenerationMode );
    if( _modelData.GenerationMode == GenerationMode::Approximate )
    {
        _task.SetMaxRandomTries( _modelData.MaxApproxTries );
    }

    // first resolve all submodels:
    //  each submodel will be a new model linked to a root model
    //  all parameters not assigned to any submodel will be linked to the root

    // create a map of all parameter iterators, this will guide the rest of the translation
    CParamMap paramMap;

    for( size_t index = 0; index < _modelData.Parameters.size(); ++index )
    {
        CModelParameter& param = _modelData.Parameters[ index ];

        Parameter* gcdParam = new Parameter( UNDEFINED_ORDER, index, static_cast<int>( param.Values.size() ),
                                             param.Name, param.IsResultParameter );

        // find out and assign weights to values
        // we don't have to care for the clean-up of the structure, Parameter's destructor will clean it
        vector< int > weightVector;
        for( auto & value : param.Values )
        {
            weightVector.push_back( value.GetWeight() );
        }
        gcdParam->SetWeights( weightVector );

        // store the structure, update its back pointer and 
        Parameters.push_back( gcdParam );
        param.GcdPointer = gcdParam;
        
        // store the pointer in a safe place for later
        paramMap.insert( make_pair( &param, gcdParam ) );
    }

    // we will store all params assigned to submodels here
    set<Parameter*> usedInSubmodels;

    // now go through all the submodels and wire up parameters to models
    for( auto & submodel : _modelData.Submodels )
    {
        Model* gcdModel = new Model( L"", GenerationType::MixedOrder, submodel.Order, _modelData.RandSeed );
        Models.push_back( gcdModel );

        for( auto & idx_param : submodel.Parameters )
        {
            // idx_param is an index of a parameter in ModelData.Parameters collection
            // to find a submodel in a guiding map let's locate that parameter and get an iterator
            vector< CModelParameter >::iterator i_param = _modelData.Parameters.begin() + idx_param;
            CParamMap::iterator found = paramMap.find( &(*i_param) );
            assert( found != paramMap.end() );

            // insert
            gcdModel->AddParameter( found->second );
            usedInSubmodels.insert( found->second );
        }
    }

    // wire up all submodels to a root model
    for( auto & model : Models )
    {
        if( rootModel != model )
        {
            rootModel->AddSubmodel( model );
        }
    }

    // for outstanding parameters we have two options:
    // 1. if any submodels were explicitly defined by a user we should create a submodel for each
    //    outstanding parameter; all such submodels should be uplinked to the root
    // 2. if no submodels were defined we just put params directly to the root
    if( usedInSubmodels.size() != paramMap.size() )
    {
        if( _modelData.Submodels.size() > 0 )
        {
            for( auto & iparam : paramMap )
            {
                if( usedInSubmodels.find( iparam.second ) != usedInSubmodels.end() )
                {
                    continue;
                }

                Model* subModel = new Model( L"", GenerationType::MixedOrder, 1, _modelData.RandSeed );
                Models.push_back( subModel );
                rootModel->AddSubmodel( subModel );

                subModel->AddParameter( iparam.second );
            }
        }
        else
        {
            for( auto & iparam : paramMap )
            {
                rootModel->AddParameter( iparam.second );
            }
        }
    }

    // add seeding rows
    for( auto & seed : _modelData.RowSeeds )
    {
        RowSeed rowSeed;
        for( auto & item : seed )
        {
            // find a pointer to Parameter and ordinal number of the value
            vector<CModelParameter>::iterator param = _modelData.FindParameterByName( item.first );
            assert( param != _modelData.Parameters.end() );
            int nVal = param->GetValueOrdinal( item.second, _modelData.CaseSensitive );
            if( nVal >= 0 )
            {
                rowSeed.insert( make_pair( param->GcdPointer, nVal ) );
            }
        }
        _task.AddRowSeed( rowSeed );
    }

    // make sure all order fields in models are set appropriately
    if( !fixModelAndSubmodelOrder() )
    {
        return( ErrorCode::ErrorCode_BadModel );
    }
    
    // add exclusions for negative values
    addExclusionsForNegativeRun();

    // add user-specified exclusions now
    
    // parse the constraints and make exclusions out of them
    ConstraintsInterpreter interpreter( _modelData, Parameters );
    if( !interpreter.ConvertToExclusions( Exclusions ) )
    {
        return( ErrorCode::ErrorCode_BadConstraints );
    }
    _constraintWarnings.assign( interpreter.GetWarnings().begin(), interpreter.GetWarnings().end() );

    if( _modelData.Verbose )
    {
        PrintLogHeader( L"Initial set of exclusions" );
        PrintGcdExclusions();
    }

    // add each exclusion to that model in the hierarchy which is the most suitable:
    //  1. a subtree of that model must have all the parameters of the exclusion
    //  2. no lower subtree satisfies the condition 1)
    for( auto & excl : Exclusions )
    {
        _task.AddExclusion( const_cast<Exclusion&> ( excl ) );
    }

    _task.PrepareForGeneration();

    // at this point we don't need gcdData.Exclusions anymore
    Exclusions.clear();
    __insert( Exclusions, _task.GetExclusions().begin(), _task.GetExclusions().end() );

    if( _modelData.Verbose )
    {
        PrintLogHeader( L"After derivation" );
        PrintGcdExclusions();
    }

    return( ErrorCode::ErrorCode_Success );
}