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( ¶m, 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 );
}