void Model::processExclusions()

in api/model.cpp [1142:1217]


void Model::processExclusions( ComboCollection& vecCombo )
{
    // Sort every parameter's collection of combinations to prepare for set intersection
    for( vector<Parameter*>::iterator ip = m_parameters.begin(); ip != m_parameters.end(); ++ip )
    {
        ( *ip )->SortCombinations();
    }

    for( ExclusionCollection::iterator iexcl = m_exclusions.begin(); iexcl != m_exclusions.end(); ++iexcl )
    {
        // paranoia; shouldn't happen
        assert( !iexcl->empty() );
        if( iexcl->empty() ) continue;

        // form the intersection of the combinations associated with each of the
        //  parameters that make up this exclusion
        ComboCollection intersection;
        Exclusion::iterator iexclterm = iexcl->begin();
        Parameter* sourceParam = iexclterm->first;
        ComboCollection::const_iterator posCandidate = sourceParam->GetCombinationBegin();
        while( true )
        {
            // We're going around and around...
            if( iexcl->end() == ++iexclterm )
            {
                iexclterm = iexcl->begin();
            }

            if( iexclterm->first == sourceParam )
            {
                intersection.push_back( *posCandidate );
                if( ++posCandidate == sourceParam->GetCombinationEnd() ) break;
            }
            // find next >= in this param
            ComboCollection::const_iterator posLB = lower_bound( iexclterm->first->GetCombinationBegin(),
                                                                 iexclterm->first->GetCombinationEnd(),
                                                                 *posCandidate, CombinationPtrSortPred() );
            if( iexclterm->first->GetCombinationEnd() == posLB ) break;
            
            // if >, reset candidate and source
            if( *posLB != *posCandidate )
            {
                posCandidate = posLB;
                sourceParam = iexclterm->first;
            }
        }
        // If the result is empty, make a new combination from the exclusion,
        // mark all of its members satisfied, and make sure all the parameters in the new
        // combination still have sorted combination collections.
        if( intersection.empty() )
        {
            Combination *pNewCombo = new Combination( this );
            int size = 1;
            for( Exclusion::iterator ix = iexcl->begin(); ix != iexcl->end(); ++ix )
            {
                pNewCombo->PushParameter( ( ix->first ) );
                ix->first->LinkCombination( pNewCombo );
                ix->first->SortCombinations();
                size *= ix->first->GetValueCount();
            }
            // Set size of combination's bit vector
            pNewCombo->SetMapSize( size, COVERED );
            vecCombo.push_back( pNewCombo );
            intersection.push_back( pNewCombo );
        }

        for( ComboCollection::iterator ic = intersection.begin(); ic != intersection.end(); ++ic )
        {
            // all exclusions must be applied to the combo and not just the current one
            for( ExclusionCollection::iterator ie = m_exclusions.begin(); ie != m_exclusions.end(); ++ie )
            {
                ( *ic )->ApplyExclusion( const_cast<Exclusion&> ( *ie ) );
            }
        }
    }
}