void ConstraintsInterpreter::interpretTerm()

in cli/gcdexcl.cpp [112:267]


void ConstraintsInterpreter::interpretTerm( IN CTerm* term, OUT CGcdExclusions& gcdExclusions )
{
    // a useful simplification: gcdData.Parameters, constrModel.Parameters, and modelData.Parameters
    // have elements in the same order thus indexes correspond to the same parameters

    // find the param in modelData
    vector< CModelParameter >::iterator found = _modelData.FindParameterByName( term->Parameter->Name );
    assert( found != _modelData.Parameters.end() );
    CModelParameter& modelParam = *found;

    // find the parameter in gcdParam
    unsigned int paramIdx = (unsigned int) distance( _modelData.Parameters.begin(), found );
    CParameter parameter = _constrModel.Parameters[ paramIdx ];

    // set up the structure: a vector of as many elements as there are values, initially set all
    //  to false; then for every value that satisfies the relation set corresponding element to true
    vector< bool > satisfyingValues;
    satisfyingValues.resize( modelParam.Values.size(), false );

    // do the solving depending on how the term looks like
    switch( term->DataType )
    {
    // everything except INs
    case TermDataType::Value:
        {
            for( size_t valueIdx = 0; valueIdx < modelParam.Values.size(); ++valueIdx )
            {
                CModelValue& value = modelParam.Values[ valueIdx ];
                if( valueSatisfiesRelation( parameter, value, term->RelationType, (CValue*) term->Data ) )
                {
                    satisfyingValues[ valueIdx ] = true;
                }
            }
            break;
        }
    // INs
    case TermDataType::ValueSet:
        {
            assert( term->RelationType == RelationType::In 
                 || term->RelationType == RelationType::NotIn );

            for( size_t valueIdx = 0; valueIdx < modelParam.Values.size(); ++valueIdx )
            {
                CModelValue& value = modelParam.Values[ valueIdx ];
            
                // any name must satisfy any value
                bool satisfied = false;
                CValueSet* valueSet = (CValueSet*) term->Data;
                for( auto & vset : *valueSet )
                {
                    if ( valueSatisfiesRelation( parameter, value, RelationType::Eq, &vset ))
                    {
                        satisfied = true;
                        break;
                    }
                }

                if (( RelationType::In    == term->RelationType &&   satisfied )
                 || ( RelationType::NotIn == term->RelationType && ! satisfied ))
                {
                    satisfyingValues[ valueIdx ] = true;
                }
            }
            break;
        }

    case TermDataType::ParameterName:
        {
            // find the param in modelData
            vector< CModelParameter >::iterator found1 = _modelData.FindParameterByName( term->Parameter->Name );
            assert( found1 != _modelData.Parameters.end() );
            CModelParameter& modelParam1 = *found1;
            unsigned int param1Idx = (unsigned int) distance( _modelData.Parameters.begin(), found1 );
            CParameter parameter1 = _constrModel.Parameters[ param1Idx ];

            vector< CModelParameter >::iterator found2 = _modelData.FindParameterByName( ((CParameter*) term->Data)->Name );
            assert( found2 != _modelData.Parameters.end() );
            CModelParameter& modelParam2 = *found2;
            unsigned int param2Idx = (unsigned int) distance( _modelData.Parameters.begin(), found2 );
            CParameter parameter2 = _constrModel.Parameters[ param2Idx ];

            for( unsigned int value1Idx = 0; value1Idx < modelParam1.Values.size(); ++value1Idx )
            {
                CModelValue value1 = modelParam1.Values[ value1Idx ];
                // if any name of value1 satifies the relation with any of the names of value2, values match
                for( unsigned int value2Idx = 0; value2Idx < modelParam2.Values.size(); ++value2Idx )
                {
                    CModelValue value2 = modelParam2.Values[ value2Idx ];

                    for( auto & name2 : value2.GetNamesForComparisons() )
                    {
                        // create temp CValue to use compare function
                        CValue* v2;
                        if ( DataType::Number == parameter2.Type )
                        {
                            v2 = new CValue( stringToNumber( name2 ));
                        }
                        else
                        {
                            v2 = new CValue( name2 );
                        }

                        if( valueSatisfiesRelation( parameter1, value1, term->RelationType, v2 ))
                        {
                            Exclusion newExcl;

                            newExcl.insert( make_pair( _gcdParameters[ param1Idx ], value1Idx ));
                            newExcl.insert( make_pair( _gcdParameters[ param2Idx ], value2Idx ));

                            gcdExclusions.insert( newExcl );
                        }
                        delete( v2 );
                    }
                }
            }
        }
    }

    // satisfying values for Value and ValueSet must be now converted into exclusions
    // for ParameterName terms this has been done already
    if ( term->DataType != TermDataType::ParameterName )
    {
        // warn if no value or all values satisfy the relation
        bool oneSatifies = false;
        bool allSatisfy  = true;
        for( auto value : satisfyingValues )
        {
            if ( value )
            {
                oneSatifies = true;
            }
            else
            {
                allSatisfy  = false;
            }
        }

        if ( ! oneSatifies || allSatisfy )
        {
            wstring s = L"All or no values satisfy relation ";
            s += (term->RawText).c_str();
            _warnings.push_back( s );
        }

        // create exclusions
        for( unsigned int idx = 0; idx < satisfyingValues.size(); ++idx )
        {
            if( satisfyingValues[ idx ] )
            {
                Exclusion newExcl;
                newExcl.insert( make_pair( _gcdParameters[ paramIdx ], idx ));
                gcdExclusions.insert( newExcl );
            }
        }
    }
}