neoml icon indicating copy to clipboard operation
neoml copied to clipboard

CMatchingGenerator misses some obvious matches

Open PeterMinin opened this issue 3 years ago • 0 comments

For some inputs CMatchingGenerator generates suboptimal matchings. Certain objects are effectively left unmatched, even though they have a match in the other set. Here is a test I wrote that should pass but is currently failing. I found a few "bad" examples, this is one of the smallest. Here, two checks are passing, but the last one is failing: EXPECT_EQ( 7, FindMatchForLeft( 5 ) ). Instead, left no.5 is matched to a different element with a score of 0.

TEST( CMatchingGenerator, UniqueMatches6x8 )
{
    struct CMyPair {
        typedef int Quality;

        int LeftIndex = -1;
        int RightIndex = -1;
        Quality Score = 0;

        Quality Penalty() const { return 1 - Score; }
    };
    const int numLeft = 6;
    const int numRight = 8;
    const int pairScores[numRight][numLeft] = {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 1, 0, 0},  // Left #3 matches right #5
        {0, 0, 0, 0, 1, 0},  // Left #4 matches right #6
        {0, 0, 0, 0, 0, 1}   // Left #5 matches right #7
    };
    NeoML::CMatchingGenerator< CMyPair > generator( numLeft, numRight, 0, INT_MAX );
    for( int leftInd = 0; leftInd < numLeft; ++leftInd ) {
        for( int rightInd = 0; rightInd < numRight; ++rightInd ) {
            CMyPair& pair = generator.PairMatrix()(leftInd, rightInd);
            pair.LeftIndex = leftInd;
            pair.RightIndex = rightInd;
            pair.Score = pairScores[rightInd][leftInd];
        }
    }
    generator.Build();
    CArray<CMyPair> matching;
    generator.GetNextMatching( matching );
    const auto& FindMatchForLeft = [&matching]( int leftInd )
    {
        for( const CMyPair& pair : matching ) {
            if( pair.LeftIndex == leftInd ) {
                return pair.RightIndex;
            }
        }
        return NotFound;
    };
    EXPECT_EQ( 5, FindMatchForLeft( 3 ) );
    EXPECT_EQ( 6, FindMatchForLeft( 4 ) );
    EXPECT_EQ( 7, FindMatchForLeft( 5 ) );
}

PeterMinin avatar Aug 13 '21 08:08 PeterMinin